Skip to content

Commit 0e7b571

Browse files
authored
Merge pull request #60 from braun-embedded/flash
Add Flash API
2 parents 1330097 + 1257ba6 commit 0e7b571

File tree

10 files changed

+551
-1
lines changed

10 files changed

+551
-1
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ required-features = ["rt"]
111111
name = "button_irq_rtfm"
112112
required-features = ["rt"]
113113

114+
[[example]]
115+
name = "flash"
116+
required-features = ["rt","stm32l082"]
117+
114118
[[example]]
115119
name = "i2c_dma"
116120
required-features = ["rt","stm32l0x2"]

build.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::env;
2-
use std::fs::File;
2+
use std::fs::{self, File};
33
use std::io::Write;
44
use std::path::PathBuf;
55

@@ -48,4 +48,23 @@ fn main() {
4848
}
4949

5050
println!("cargo:rerun-if-changed=build.rs");
51+
52+
53+
// Copy the binary blog required by the Flash API somewhere the linker can
54+
// find it, and tell Cargo to link it.
55+
56+
let blob_name = "flash";
57+
let blob_file = format!("lib{}.a", blob_name);
58+
let blob_path = format!("flash-code/{}", blob_file);
59+
60+
fs::copy(
61+
&blob_path,
62+
out.join(format!("{}", blob_file)),
63+
)
64+
.expect("Failed to copy binary blog for Flash API");
65+
66+
println!("cargo:rustc-link-lib=static={}", blob_name);
67+
println!("cargo:rustc-link-search={}", out.display());
68+
69+
println!("cargo:rerun-if-changed={}", blob_path);
5170
}

examples/flash.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
5+
extern crate panic_semihosting;
6+
7+
8+
use cortex_m_rt::entry;
9+
use stm32l0xx_hal::{
10+
prelude::*,
11+
flash::{
12+
FLASH,
13+
FLASH_START,
14+
flash_size_in_kb,
15+
},
16+
pac,
17+
rcc,
18+
};
19+
20+
21+
#[entry]
22+
fn main() -> ! {
23+
let cp = cortex_m::Peripherals::take().unwrap();
24+
let dp = pac::Peripherals::take().unwrap();
25+
26+
let mut rcc = dp.RCC.freeze(rcc::Config::hsi16());
27+
let mut flash = FLASH::new(dp.FLASH, &mut rcc);
28+
let gpiob = dp.GPIOB.split(&mut rcc);
29+
30+
let mut led = gpiob.pb2.into_push_pull_output();
31+
32+
// Get the delay provider.
33+
let mut delay = cp.SYST.delay(rcc.clocks);
34+
35+
// This should be the first word in the second flash bank. Since this
36+
// example should be quite small, we can be reasonably sure that it fully
37+
// fits into the first flash bank. This means we won't overwrite our own
38+
// code or stall execution.
39+
//
40+
// This example requires STM32L082, which has 2 banks.
41+
let address = FLASH_START + flash_size_in_kb() / 2 * 1024;
42+
let address = address as *mut u32;
43+
44+
flash.erase_flash_page(address)
45+
.expect("Failed to erase Flash page (1)");
46+
for i in 0 .. 32 {
47+
let word = unsafe { *address.offset(i * 4) };
48+
assert_eq!(word, 0);
49+
}
50+
51+
flash.write_word(address, 0x12345678)
52+
.expect("Failed to write word");
53+
assert_eq!(unsafe { *address }, 0x12345678);
54+
55+
flash.erase_flash_page(address)
56+
.expect("Failed to erase Flash page (2)");
57+
for i in 0 .. 32 {
58+
let word = unsafe { *address.offset(i * 4) };
59+
assert_eq!(word, 0);
60+
}
61+
62+
let words = [
63+
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
64+
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
65+
];
66+
67+
flash.write_flash_half_page(address, &words)
68+
.expect("Failed to write Flash half-page");
69+
70+
for (i, &expected) in words.iter().enumerate() {
71+
let actual = unsafe { *address.offset(i as isize) };
72+
assert_eq!(expected, actual);
73+
}
74+
75+
// Blink LED to indicate we haven't panicked.
76+
loop {
77+
led.set_high().unwrap();
78+
delay.delay_ms(500_u16);
79+
80+
led.set_low().unwrap();
81+
delay.delay_ms(500_u16);
82+
}
83+
}

flash-code/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# C compiler output
2+
/*.o

flash-code/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C code used by the FLASH API to write half-pages. Contains both the source code, as well as a precompiled binary.
2+
3+
The binary can be compiled using `compile.sh` in this directory. See `src/flash.rs` for an explanation of why this is necessary.

flash-code/compile.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
3+
# Compiles `flash.c` using the GCC toolchain. `build.rs` makes sure that the
4+
# resulting library is linked.
5+
#
6+
# Since requiring all users of this HAL to have the GCC toolchain installed
7+
# would be inconvenient for many, the resulting library is checked into the
8+
# repository. After every change to `flash.c`, you need to call this script
9+
# manually and commit the updated binary.
10+
11+
arm-none-eabi-gcc -march=armv6s-m -ffreestanding -O2 -c flash.c &&
12+
arm-none-eabi-ar r libflash.a flash.o

flash-code/flash.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stdint.h>
2+
3+
4+
// Called from src/flash.rs. See comment there for an explanation of why a C
5+
// function is necessary.
6+
__attribute__((section(".data")))
7+
void write_half_page(uint32_t *address, uint32_t *words) {
8+
uint32_t i = 0;
9+
while (i < 16) {
10+
*(address + i) = *(words + i);
11+
i++;
12+
}
13+
}

flash-code/libflash.a

896 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)