Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to Flash.rs #83

Merged
merged 6 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions examples/flash_with_rtic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#![allow(unsafe_code)]
#![allow(warnings)]
#![allow(missing_docs)]
#![allow(unused_variables)]
#![no_main]
#![no_std]

#[rtic::app(device = stm32g4xx_hal::stm32g4::stm32g474, peripherals = true)]
mod app {
use stm32g4xx_hal::flash::{FlashExt, FlashSize, FlashWriter, Parts};
use stm32g4xx_hal::prelude::*;
use stm32g4xx_hal::rcc::{PllConfig, RccExt};

use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics

// Resources shared between tasks
#[shared]
struct Shared {}

// Local resources to specific tasks (cannot be shared)
#[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) {
// let dp = Peripherals::take().unwrap();
// let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals");

let dp = cx.device;
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 mut rcc = rcc.freeze(clock_config);

unsafe {
let mut flash = &(*stm32g4xx_hal::stm32::FLASH::ptr());
flash.acr.modify(|_, w| {
w.latency().bits(0b1000) // 8 wait states
});
}

// *** FLASH Memory ***
//let mut data = [0xBE, 0xEF, 0xCA, 0xFE];
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 sixteen_bytes = [
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
0xDE, 0xF0 as u8,
];
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

flash_writer.erase(0x1FC00, 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(0x1FC00 + i * FLASH_SPACING, &one_byte, false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constant instead magic numbers

assert!(result.is_err());
no111u3 marked this conversation as resolved.
Show resolved Hide resolved
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(0x1FC00 + i * FLASH_SPACING, &one_byte, true);
assert!(result.is_ok());
}
1 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result = flash_writer.write(0x1FC00 + 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(0x1FC00 + i * FLASH_SPACING, &two_bytes, true);
assert!(result.is_ok());
}
2 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result =
flash_writer.write(0x1FC00 + i * FLASH_SPACING, &three_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(0x1FC00 + i * FLASH_SPACING, &three_bytes, true);
assert!(result.is_ok());
}
3 => {
// This test should fail, as the data needs to be divisible by 8 and force padding is false
let result =
flash_writer.write(0x1FC00 + i * FLASH_SPACING, &four_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(0x1FC00 + i * FLASH_SPACING, &four_bytes, true);
assert!(result.is_ok());
}
4 => flash_writer
.write(0x1FC00 + i * FLASH_SPACING, &eight_bytes, false)
.unwrap(),
5 => flash_writer
.write(0x1FC00 + i * 16, &sixteen_bytes, false)
.unwrap(),
_ => (),
}
}

for i in 0..6 {
match i {
0 => {
let bytes = flash_writer.read(0x1FC00 as u32, one_byte.len()).unwrap();
assert!(compare_arrays(&bytes, &one_byte));
}
1 => {
let bytes = flash_writer
.read(0x1FC00 + i * FLASH_SPACING, two_bytes.len())
.unwrap();
assert!(compare_arrays(&bytes, &two_bytes));
}
2 => {
let bytes = flash_writer
.read(0x1FC00 + i * FLASH_SPACING, three_bytes.len())
.unwrap();
assert!(compare_arrays(&bytes, &three_bytes));
}
3 => {
let bytes = flash_writer
.read(0x1FC00 + i * FLASH_SPACING, four_bytes.len())
.unwrap();
assert!(compare_arrays(&bytes, &four_bytes));
}
4 => {
let bytes = flash_writer
.read(0x1FC00 + i * FLASH_SPACING, eight_bytes.len())
.unwrap();
assert!(compare_arrays(&bytes, &eight_bytes));
}
5 => {
let bytes = flash_writer
.read(0x1FC00 + i * FLASH_SPACING, sixteen_bytes.len())
.unwrap();
assert!(compare_arrays(&bytes, &sixteen_bytes));
}
_ => (),
}
}

(
// Initialization of shared resources
Shared {},
// Initialization of task local resources
Local {},
// Move the monotonic timer to the RTIC run-time, this enables
// scheduling
init::Monotonics(),
)
}

// Background task, runs whenever no other tasks are running
#[idle]
fn idle(mut cx: idle::Context) -> ! {
loop {
// Sleep until next interrupt
cortex_m::asm::wfi();
}
}
}
Loading