Skip to content

Commit

Permalink
Trim down flash_with_rtic example
Browse files Browse the repository at this point in the history
  • Loading branch information
usbalbin committed Dec 18, 2023
1 parent 7e3f7f6 commit 7f71d41
Showing 1 changed file with 41 additions and 237 deletions.
278 changes: 41 additions & 237 deletions examples/flash_with_rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

mod utils;

#[rtic::app(device = stm32g4xx_hal::stm32g4::stm32g474, peripherals = true)]
#[rtic::app(device = stm32g4xx_hal::stm32, peripherals = true)]
mod app {
use crate::utils::logger;
use stm32g4xx_hal::flash::{FlashExt, FlashSize, FlashWriter, Parts};
Expand All @@ -25,18 +25,6 @@ mod app {
#[local]
struct Local {}

fn compare_arrays(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
for i in 0..a.len() {
if a[i] != b[i] {
return false;
}
}
true
}

#[init]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
crate::utils::logger::init();
Expand All @@ -45,258 +33,74 @@ mod app {
let cp = cx.core;

let rcc = dp.RCC.constrain();
let mut pll_config = stm32g4xx_hal::rcc::PllConfig::default();

// Sysclock is based on PLL_R
pll_config.mux = stm32g4xx_hal::rcc::PLLSrc::HSI; // 16MHz
pll_config.n = stm32g4xx_hal::rcc::PllNMul::MUL_32;
pll_config.m = stm32g4xx_hal::rcc::PllMDiv::DIV_2; // f(vco) = 16MHz*32/2 = 256MHz
pll_config.r = Some(stm32g4xx_hal::rcc::PllRDiv::DIV_2); // f(sysclock) = 256MHz/2 = 128MHz

// Note to future self: The AHB clock runs the timers, among other things.
// Please refer to the Clock Tree manual to determine if it is worth
// changing to a lower speed for battery life savings.
let mut clock_config = stm32g4xx_hal::rcc::Config::default()
.pll_cfg(pll_config)
.clock_src(stm32g4xx_hal::rcc::SysClockSrc::PLL);

// After clock configuration, the following should be true:
// Sysclock is 128MHz
// AHB clock is 128MHz
// APB1 clock is 128MHz
// APB2 clock is 128MHz
// The ADC will ultimately be put into synchronous mode and will derive
// its clock from the AHB bus clock, with a prescalar of 2 or 4.

let pwr = dp.PWR.constrain().freeze();
let mut rcc = rcc.freeze(clock_config, pwr);

unsafe {
let mut flash = &(*stm32g4xx_hal::stm32::FLASH::ptr());
flash.acr.modify(|_, w| {
w.latency().bits(0b1000) // 8 wait states
});
}
let mut rcc = rcc.freeze(stm32g4xx_hal::rcc::Config::hsi(), pwr);
let mut delay = cp.SYST.delay(&rcc.clocks);

// *** FLASH Memory ***
let one_byte = [0x12 as u8];
let two_bytes = [0xAB, 0xCD as u8];
let three_bytes = [0x12, 0x34, 0x56 as u8];
let four_bytes = [0xAB, 0xCD, 0xEF, 0xBA as u8];
let eight_bytes = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 as u8];
let one_byte = [0x12];
let two_bytes = [0xAB, 0xCD];
let three_bytes = [0x12, 0x34, 0x56];
let four_bytes = [0xAB, 0xCD, 0xEF, 0xBA];
let eight_bytes = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
let sixteen_bytes = [
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
0xDE, 0xF0 as u8,
0xDE, 0xF0,
];
let mut flash = dp.FLASH.constrain();
let mut flash_writer = flash.writer::<2048>(FlashSize::Sz256K);

const FLASH_SPACING: u32 = 16; // Separate flash writes by 16 bytes
const FLASH_EXAMPLE_START_ADDRESS: u32 = 0x1FC00;

let address = |i| FLASH_EXAMPLE_START_ADDRESS + i as u32 * FLASH_SPACING;

logger::info!(
"Erasing 128 bytes at address {}",
"Erasing 128 bytes at address {:#X}",
FLASH_EXAMPLE_START_ADDRESS
);
flash_writer
.erase(FLASH_EXAMPLE_START_ADDRESS, 128)
.unwrap(); // Erase entire page

for i in 0..6 {
match i {
0 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&one_byte,
false,
);
assert!(result.is_err());
assert_eq!(
result.err().unwrap(),
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
);

// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&one_byte,
true,
);
assert!(result.is_ok());
logger::info!(
"Wrote 1 byte to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
1 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&two_bytes,
false,
);
assert!(result.is_err());
assert_eq!(
result.err().unwrap(),
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
);

// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&two_bytes,
true,
);
assert!(result.is_ok());
logger::info!(
"Wrote 2 bytes to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
2 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&three_bytes,
false,
);
assert!(result.is_err());
assert_eq!(
result.err().unwrap(),
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
);
let datasets = [
&one_byte[..],
&two_bytes[..],
&three_bytes[..],
&four_bytes[..],
&eight_bytes[..],
&sixteen_bytes[..],
];

// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&three_bytes,
true,
);
assert!(result.is_ok());
logger::info!(
"Wrote 3 bytes to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
3 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&four_bytes,
false,
);
assert!(result.is_err());
assert_eq!(
result.err().unwrap(),
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
);
for (i, data) in datasets.into_iter().enumerate() {
let address = address(i);
let mut do_write = |force_padding| flash_writer.write(address, &data, force_padding);

// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
let result = flash_writer.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&four_bytes,
true,
);
assert!(result.is_ok());
logger::info!(
"Wrote 4 bytes to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
4 => {
flash_writer
.write(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
&eight_bytes,
false,
)
.unwrap();
logger::info!(
"Wrote 8 bytes to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
5 => {
flash_writer
.write(FLASH_EXAMPLE_START_ADDRESS + i * 16, &sixteen_bytes, false)
.unwrap();
logger::info!(
"Wrote 16 bytes to address {}",
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING
);
}
_ => (),
if data.len() % 8 != 0 {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
assert_eq!(
do_write(false),
Err(stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8)
);
}
}

// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
do_write(true).unwrap();
logger::info!("Wrote {} byte(s) to address {:#X}", data.len(), address);
}
logger::info!("Validating data written data by performing read and compare");

for i in 0..6 {
match i {
0 => {
let bytes = flash_writer
.read(FLASH_EXAMPLE_START_ADDRESS as u32, one_byte.len())
.unwrap();
assert!(compare_arrays(&bytes, &one_byte));
logger::info!("Validated 1 byte data");
}
1 => {
let bytes = flash_writer
.read(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
two_bytes.len(),
)
.unwrap();
assert!(compare_arrays(&bytes, &two_bytes));
logger::info!("Validated 2 byte data");
}
2 => {
let bytes = flash_writer
.read(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
three_bytes.len(),
)
.unwrap();
assert!(compare_arrays(&bytes, &three_bytes));
logger::info!("Validated 3 byte data");
}
3 => {
let bytes = flash_writer
.read(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
four_bytes.len(),
)
.unwrap();
assert!(compare_arrays(&bytes, &four_bytes));
logger::info!("Validated 4 byte data");
}
4 => {
let bytes = flash_writer
.read(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
eight_bytes.len(),
)
.unwrap();
assert!(compare_arrays(&bytes, &eight_bytes));
logger::info!("Validated 8 byte data");
}
5 => {
let bytes = flash_writer
.read(
FLASH_EXAMPLE_START_ADDRESS + i * FLASH_SPACING,
sixteen_bytes.len(),
)
.unwrap();
assert!(compare_arrays(&bytes, &sixteen_bytes));
logger::info!("Validated 5 byte data");
}
_ => (),
}
for (i, data) in datasets.into_iter().enumerate() {
logger::info!("Stuff: {}", i);
let mut bytes = [0; 16];
flash_writer.read_exact(address(i), &mut bytes[..data.len()]);

assert_eq!(&bytes[..data.len()], *data);
logger::info!("Validated {} byte data", data.len());
}

logger::info!(
"Finished flash example at address {}",
"Finished flash example at address {:#X}",
FLASH_EXAMPLE_START_ADDRESS
);

Expand Down

0 comments on commit 7f71d41

Please sign in to comment.