aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-11 01:37:19 +0000
committerGitHub <[email protected]>2022-07-11 01:37:19 +0000
commit99f4fd33b493f11ec3202eb98fc3ae9e18b9d589 (patch)
tree931e4ebbb9927011c885779cc3339072b129d34c
parent9753f767946d79c5987c166e513150aca98ec042 (diff)
parent3271ba36e439b037a9f775ccc9b7de8511cbcf7a (diff)
Merge #859
859: Add F4 flash driver r=Dirbaio a=chemicstry Pending on https://github.com/embassy-rs/stm32-data/pull/152 Co-authored-by: chemicstry <[email protected]>
-rw-r--r--embassy-stm32/src/flash/f4.rs168
-rw-r--r--embassy-stm32/src/flash/mod.rs1
-rw-r--r--embassy-stm32/src/lib.rs4
-rw-r--r--examples/stm32f4/Cargo.toml1
-rw-r--r--examples/stm32f4/src/bin/flash.rs57
m---------stm32-data0
6 files changed, 230 insertions, 1 deletions
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
new file mode 100644
index 000000000..f6dc7e955
--- /dev/null
+++ b/embassy-stm32/src/flash/f4.rs
@@ -0,0 +1,168 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile;
3
4use atomic_polyfill::{fence, Ordering};
5
6use super::{ERASE_SIZE, FLASH_BASE, FLASH_SIZE};
7use crate::flash::Error;
8use crate::pac;
9
10// Only available on some devices
11const SECOND_BANK_OFFSET: usize = FLASH_SIZE / 2;
12const SECOND_BANK_SECTOR_START: u32 = 12;
13
14unsafe fn is_dual_bank() -> bool {
15 match FLASH_SIZE / 1024 {
16 // 1 MB devices depend on configuration
17 1024 => {
18 if cfg!(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)) {
19 pac::FLASH.optcr().read().db1m()
20 } else {
21 false
22 }
23 }
24 // 2 MB devices are always dual bank
25 2048 => true,
26 // All other devices are single bank
27 _ => false,
28 }
29}
30
31pub(crate) unsafe fn lock() {
32 pac::FLASH.cr().modify(|w| w.set_lock(true));
33}
34
35pub(crate) unsafe fn unlock() {
36 pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123));
37 pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB));
38}
39
40pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error> {
41 pac::FLASH.cr().write(|w| {
42 w.set_pg(true);
43 w.set_psize(pac::flash::vals::Psize::PSIZE32);
44 });
45
46 let ret = {
47 let mut ret: Result<(), Error> = Ok(());
48 let mut offset = offset;
49 for chunk in buf.chunks(super::WRITE_SIZE) {
50 for val in chunk.chunks(4) {
51 write_volatile(offset as *mut u32, u32::from_le_bytes(val[0..4].try_into().unwrap()));
52 offset += val.len() as u32;
53
54 // prevents parallelism errors
55 fence(Ordering::SeqCst);
56 }
57
58 ret = blocking_wait_ready();
59 if ret.is_err() {
60 break;
61 }
62 }
63 ret
64 };
65
66 pac::FLASH.cr().write(|w| w.set_pg(false));
67
68 ret
69}
70
71unsafe fn get_sector(addr: u32) -> u8 {
72 let offset = addr - FLASH_BASE as u32;
73
74 let sector = if is_dual_bank() {
75 let bank = offset / SECOND_BANK_OFFSET as u32;
76 let offset_in_bank = offset % SECOND_BANK_OFFSET as u32;
77
78 let sector_in_bank = if offset_in_bank >= ERASE_SIZE as u32 / 2 {
79 4 + offset_in_bank / ERASE_SIZE as u32
80 } else {
81 offset_in_bank / (ERASE_SIZE as u32 / 8)
82 };
83
84 if bank == 1 {
85 SECOND_BANK_SECTOR_START + sector_in_bank
86 } else {
87 sector_in_bank
88 }
89 } else {
90 if offset >= ERASE_SIZE as u32 / 2 {
91 4 + offset / ERASE_SIZE as u32
92 } else {
93 offset / (ERASE_SIZE as u32 / 8)
94 }
95 };
96
97 sector as u8
98}
99
100pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> {
101 let start_sector = get_sector(from);
102 let end_sector = get_sector(to);
103
104 for sector in start_sector..end_sector {
105 let ret = erase_sector(sector as u8);
106 if ret.is_err() {
107 return ret;
108 }
109 }
110
111 Ok(())
112}
113
114unsafe fn erase_sector(sector: u8) -> Result<(), Error> {
115 let bank = sector / SECOND_BANK_SECTOR_START as u8;
116 let snb = (bank << 4) + (sector % SECOND_BANK_SECTOR_START as u8);
117
118 pac::FLASH.cr().modify(|w| {
119 w.set_ser(true);
120 w.set_snb(snb)
121 });
122
123 pac::FLASH.cr().modify(|w| {
124 w.set_strt(true);
125 });
126
127 let ret: Result<(), Error> = blocking_wait_ready();
128
129 clear_all_err();
130
131 ret
132}
133
134pub(crate) unsafe fn clear_all_err() {
135 pac::FLASH.sr().write(|w| {
136 w.set_pgserr(true);
137 w.set_pgperr(true);
138 w.set_pgaerr(true);
139 w.set_wrperr(true);
140 w.set_eop(true);
141 });
142}
143
144pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> {
145 loop {
146 let sr = pac::FLASH.sr().read();
147
148 if !sr.bsy() {
149 if sr.pgserr() {
150 return Err(Error::Seq);
151 }
152
153 if sr.pgperr() {
154 return Err(Error::Parallelism);
155 }
156
157 if sr.pgaerr() {
158 return Err(Error::Unaligned);
159 }
160
161 if sr.wrperr() {
162 return Err(Error::Protected);
163 }
164
165 return Ok(());
166 }
167 }
168}
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 31ca243a6..59ca59f65 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -10,6 +10,7 @@ const FLASH_END: usize = FLASH_BASE + FLASH_SIZE;
10 10
11#[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")] 11#[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")]
12#[cfg_attr(flash_f3, path = "f3.rs")] 12#[cfg_attr(flash_f3, path = "f3.rs")]
13#[cfg_attr(flash_f4, path = "f4.rs")]
13#[cfg_attr(flash_f7, path = "f7.rs")] 14#[cfg_attr(flash_f7, path = "f7.rs")]
14#[cfg_attr(flash_h7, path = "h7.rs")] 15#[cfg_attr(flash_h7, path = "h7.rs")]
15mod family; 16mod family;
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 7be0c77ea..8b8168589 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -39,7 +39,9 @@ pub mod i2c;
39 39
40#[cfg(crc)] 40#[cfg(crc)]
41pub mod crc; 41pub mod crc;
42#[cfg(any(flash_l0, flash_l1, flash_wl, flash_wb, flash_l4, flash_f3, flash_f7, flash_h7))] 42#[cfg(any(
43 flash_l0, flash_l1, flash_wl, flash_wb, flash_l4, flash_f3, flash_f4, flash_f7, flash_h7
44))]
43pub mod flash; 45pub mod flash;
44pub mod pwm; 46pub mod pwm;
45#[cfg(rng)] 47#[cfg(rng)]
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index de33ffad8..100c0e608 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -19,6 +19,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
19futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 19futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
20heapless = { version = "0.7.5", default-features = false } 20heapless = { version = "0.7.5", default-features = false }
21nb = "1.0.0" 21nb = "1.0.0"
22embedded-storage = "0.3.0"
22 23
23usb-device = "0.2" 24usb-device = "0.2"
24usbd-serial = "0.1.1" 25usbd-serial = "0.1.1"
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs
new file mode 100644
index 000000000..b531d6f13
--- /dev/null
+++ b/examples/stm32f4/src/bin/flash.rs
@@ -0,0 +1,57 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{info, unwrap};
6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer};
8use embassy_stm32::flash::Flash;
9use embassy_stm32::Peripherals;
10use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy::main]
14async fn main(_spawner: Spawner, p: Peripherals) {
15 info!("Hello Flash!");
16
17 const ADDR: u32 = 0x10_0000;
18
19 // wait a bit before accessing the flash
20 Timer::after(Duration::from_millis(300)).await;
21
22 let mut f = Flash::unlock(p.FLASH);
23
24 info!("Reading...");
25 let mut buf = [0u8; 32];
26 unwrap!(f.read(ADDR, &mut buf));
27 info!("Read: {=[u8]:x}", buf);
28
29 info!("Erasing...");
30 unwrap!(f.erase(ADDR, ADDR + 128 * 1024));
31
32 info!("Reading...");
33 let mut buf = [0u8; 32];
34 unwrap!(f.read(ADDR, &mut buf));
35 info!("Read after erase: {=[u8]:x}", buf);
36
37 info!("Writing...");
38 unwrap!(f.write(
39 ADDR,
40 &[
41 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
42 30, 31, 32
43 ]
44 ));
45
46 info!("Reading...");
47 let mut buf = [0u8; 32];
48 unwrap!(f.read(ADDR, &mut buf));
49 info!("Read: {=[u8]:x}", buf);
50 assert_eq!(
51 &buf[..],
52 &[
53 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
54 30, 31, 32
55 ]
56 );
57}
diff --git a/stm32-data b/stm32-data
Subproject b90d7cf8cb0610e333e4eef7127ae8c51955860 Subproject b13ba26f6f9b7049097e39ccc7e5e246ac023d1