Skip to content

Commit 9b31810

Browse files
committed
Added changes systec-ms
- Linter fixes - Added code comment that clarifies the need to write double words - Added an example called flash_with_rtic.rs to show flash memory use case.
1 parent d99ba9d commit 9b31810

File tree

2 files changed

+180
-2
lines changed

2 files changed

+180
-2
lines changed

examples/flash_with_rtic.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#![allow(unsafe_code)]
2+
#![allow(warnings)]
3+
#![allow(missing_docs)]
4+
#![allow(unused_variables)]
5+
#![no_main]
6+
#![no_std]
7+
8+
#[rtic::app(device = stm32g4xx_hal::stm32g4::stm32g474, peripherals = true)]
9+
mod app {
10+
use stm32g4xx_hal::flash::{FlashExt, FlashSize, FlashWriter, Parts};
11+
use stm32g4xx_hal::prelude::*;
12+
use stm32g4xx_hal::rcc::{PllConfig, RccExt};
13+
14+
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
15+
16+
// Resources shared between tasks
17+
#[shared]
18+
struct Shared {}
19+
20+
// Local resources to specific tasks (cannot be shared)
21+
#[local]
22+
struct Local {}
23+
24+
fn compare_arrays(a: &[u8], b: &[u8]) -> bool {
25+
if a.len() != b.len() {
26+
return false;
27+
}
28+
for i in 0..a.len() {
29+
if a[i] != b[i] {
30+
return false;
31+
}
32+
}
33+
true
34+
}
35+
36+
#[init]
37+
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
38+
// let dp = Peripherals::take().unwrap();
39+
// let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals");
40+
41+
let dp = cx.device;
42+
let cp = cx.core;
43+
44+
let rcc = dp.RCC.constrain();
45+
let mut pll_config = stm32g4xx_hal::rcc::PllConfig::default();
46+
47+
// Sysclock is based on PLL_R
48+
pll_config.mux = stm32g4xx_hal::rcc::PLLSrc::HSI; // 16MHz
49+
pll_config.n = stm32g4xx_hal::rcc::PllNMul::MUL_32;
50+
pll_config.m = stm32g4xx_hal::rcc::PllMDiv::DIV_2; // f(vco) = 16MHz*32/2 = 256MHz
51+
pll_config.r = Some(stm32g4xx_hal::rcc::PllRDiv::DIV_2); // f(sysclock) = 256MHz/2 = 128MHz
52+
53+
// Note to future self: The AHB clock runs the timers, among other things.
54+
// Please refer to the Clock Tree manual to determine if it is worth
55+
// changing to a lower speed for battery life savings.
56+
let mut clock_config = stm32g4xx_hal::rcc::Config::default()
57+
.pll_cfg(pll_config)
58+
.clock_src(stm32g4xx_hal::rcc::SysClockSrc::PLL);
59+
60+
// After clock configuration, the following should be true:
61+
// Sysclock is 128MHz
62+
// AHB clock is 128MHz
63+
// APB1 clock is 128MHz
64+
// APB2 clock is 128MHz
65+
// The ADC will ultimately be put into synchronous mode and will derive
66+
// its clock from the AHB bus clock, with a prescalar of 2 or 4.
67+
68+
let mut rcc = rcc.freeze(clock_config);
69+
70+
unsafe {
71+
let mut flash = &(*stm32g4xx_hal::stm32::FLASH::ptr());
72+
flash.acr.modify(|_, w| {
73+
w.latency().bits(0b1000) // 8 wait states
74+
});
75+
}
76+
77+
// *** FLASH Memory ***
78+
//let mut data = [0xBE, 0xEF, 0xCA, 0xFE];
79+
let one_byte = [0x12 as u8];
80+
let two_bytes = [0xAB, 0xCD as u8];
81+
let three_bytes = [0x12, 0x34, 0x56 as u8];
82+
let four_bytes = [0xAB, 0xCD, 0xEF, 0xBA as u8];
83+
let eight_bytes = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 as u8];
84+
let sixteen_bytes = [
85+
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
86+
0xDE, 0xF0 as u8,
87+
];
88+
let mut flash = dp.FLASH.constrain();
89+
let mut flash_writer = flash.writer::<2048>(FlashSize::Sz256K);
90+
const FLASH_SPACING: usize = 16; // Separate flash writes by 16 bytes
91+
92+
flash_writer.erase(0x1FC00, 128).unwrap(); // Erase entire page
93+
94+
for i in 0..6 {
95+
match i {
96+
0 => flash_writer
97+
.write(0x1FC00 + i * FLASH_SPACING, &one_byte)
98+
.unwrap(),
99+
1 => flash_writer
100+
.write(0x1FC00 + i * FLASH_SPACING, &two_bytes)
101+
.unwrap(),
102+
2 => flash_writer
103+
.write(0x1FC00 + i * FLASH_SPACING, &three_bytes)
104+
.unwrap(),
105+
3 => flash_writer
106+
.write(0x1FC00 + i * FLASH_SPACING, &four_bytes)
107+
.unwrap(),
108+
4 => flash_writer
109+
.write(0x1FC00 + i * FLASH_SPACING, &eight_bytes)
110+
.unwrap(),
111+
5 => flash_writer
112+
.write(0x1FC00 + i * 16, &sixteen_bytes)
113+
.unwrap(),
114+
_ => (),
115+
}
116+
}
117+
118+
for i in 0..6 {
119+
match i {
120+
0 => {
121+
let bytes = flash_writer.read(0x1FC00 as u32, one_byte.len()).unwrap();
122+
assert!(compare_arrays(&bytes, &one_byte));
123+
}
124+
1 => {
125+
let bytes = flash_writer
126+
.read(0x1FC00 + i * FLASH_SPACING, two_bytes.len())
127+
.unwrap();
128+
assert!(compare_arrays(&bytes, &two_bytes));
129+
}
130+
2 => {
131+
let bytes = flash_writer
132+
.read(0x1FC00 + i * FLASH_SPACING, three_bytes.len())
133+
.unwrap();
134+
assert!(compare_arrays(&bytes, &three_bytes));
135+
}
136+
3 => {
137+
let bytes = flash_writer
138+
.read(0x1FC00 + i * FLASH_SPACING, four_bytes.len())
139+
.unwrap();
140+
assert!(compare_arrays(&bytes, &four_bytes));
141+
}
142+
4 => {
143+
let bytes = flash_writer
144+
.read(0x1FC00 + i * FLASH_SPACING, eight_bytes.len())
145+
.unwrap();
146+
assert!(compare_arrays(&bytes, &eight_bytes));
147+
}
148+
5 => {
149+
let bytes = flash_writer
150+
.read(0x1FC00 + i * FLASH_SPACING, sixteen_bytes.len())
151+
.unwrap();
152+
assert!(compare_arrays(&bytes, &sixteen_bytes));
153+
}
154+
_ => (),
155+
}
156+
}
157+
158+
(
159+
// Initialization of shared resources
160+
Shared {},
161+
// Initialization of task local resources
162+
Local {},
163+
// Move the monotonic timer to the RTIC run-time, this enables
164+
// scheduling
165+
init::Monotonics(),
166+
)
167+
}
168+
169+
// Background task, runs whenever no other tasks are running
170+
#[idle]
171+
fn idle(mut cx: idle::Context) -> ! {
172+
loop {
173+
// Sleep until next interrupt
174+
cortex_m::asm::wfi();
175+
}
176+
}
177+
}

src/flash.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
255255
// Unlock Flash
256256
self.unlock()?;
257257

258+
// According to RM0440 Rev 7, "It is only possible to program double word (2 x 32-bit data)"
258259
for idx in (0..data.len()).step_by(8) {
259260
// Check the starting address
260261
self.valid_address(offset + idx as u32)?;
@@ -264,8 +265,8 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
264265
let write_address1 = (FLASH_START + offset + idx as u32) as *mut u32;
265266
let write_address2 = (FLASH_START + offset + 4 + idx as u32) as *mut u32;
266267

267-
let mut word1: u32 = 0;
268-
let mut word2: u32 = 0;
268+
let word1: u32;
269+
let word2: u32;
269270

270271
// Check if there is enough data to make 2 words, if there isn't, pad the data with 0xFF
271272
if idx + 8 > data.len() {

0 commit comments

Comments
 (0)