-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathalgo.rs
More file actions
146 lines (136 loc) · 4.76 KB
/
algo.rs
File metadata and controls
146 lines (136 loc) · 4.76 KB
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#![macro_use]
use core::arch::asm;
use core::num::NonZeroU32;
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
asm!("udf #0");
core::hint::unreachable_unchecked();
}
}
pub type ErrorCode = NonZeroU32;
pub trait FlashAlgo: Sized + 'static {
/// Initialize the flash algorithm.
fn new(address: u32, clock: u32, function: u32) -> Result<Self, ErrorCode>;
/// Erase entire chip. May only be called after init() with FUNCTION_ERASE
fn erase_all(&mut self) -> Result<(), ErrorCode>;
/// Erase sector. May only be called after init() with FUNCTION_ERASE
fn erase_sector(&mut self, addr: u32) -> Result<(), ErrorCode>;
/// Erase a range of memory. May only be called after init() with FUNCTION_ERASE
fn erase_range(&mut self, start_addr: u32, end_addr: u32) -> Result<(), ErrorCode>;
/// Program bytes. May only be called after init() with FUNCTION_PROGRAM
fn program_page(&mut self, addr: u32, size: u32, data: *const u8) -> Result<(), ErrorCode>;
}
#[macro_export]
macro_rules! algo {
($type:ty) => {
static mut _IS_INIT: bool = false;
static mut _ALGO_INSTANCE: MaybeUninit<$type> = MaybeUninit::uninit();
/// Initialise the Flash Algorithm
///
/// # Safety
///
/// Will disable execution from Flash. Ensure you are running from SRAM
/// and do not call any flash-based based functions.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn Init(addr: u32, clock: u32, function: u32) -> u32 {
if _IS_INIT {
UnInit();
}
match <$type as FlashAlgo>::new(addr, clock, function) {
Ok(inst) => {
_ALGO_INSTANCE.as_mut_ptr().write(inst);
_IS_INIT = true;
0
}
Err(e) => e.get(),
}
}
/// Uninitialise the Flash Algorithm
#[no_mangle]
#[link_section = ".entry"]
pub extern "C" fn UnInit() -> u32 {
unsafe {
if !_IS_INIT {
return 1;
}
_ALGO_INSTANCE.as_mut_ptr().drop_in_place();
_IS_INIT = false;
}
0
}
/// Erase the flash chip.
///
/// # Safety
///
/// Will erase the flash chip. Ensure you really want to erase the
/// flash chip.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn EraseChip() -> u32 {
if !_IS_INIT {
return 1;
}
let this = &mut *_ALGO_INSTANCE.as_mut_ptr();
match <$type as FlashAlgo>::erase_all(this) {
Ok(()) => 0,
Err(e) => e.get(),
}
}
/// Erase the a sector on the flash chip.
///
/// # Safety
///
/// Will erase the given sector. Pass a valid sector address.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn EraseSector(addr: u32) -> u32 {
if !_IS_INIT {
return 1;
}
let this = &mut *_ALGO_INSTANCE.as_mut_ptr();
match <$type as FlashAlgo>::erase_sector(this, addr) {
Ok(()) => 0,
Err(e) => e.get(),
}
}
/// Erase a range of memory on the flash chip.
/// Algo can use page/block erase commands to improve performance vs EraseSector
///
/// # Safety
///
/// Will erase all memory inside the address range.
/// Must pass a valid sector start and end address.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn EraseRange(start_addr: u32, end_addr: u32) -> u32 {
if !_IS_INIT {
return 1;
}
let this = &mut *_ALGO_INSTANCE.as_mut_ptr();
match <$type as FlashAlgo>::erase_range(this, start_addr, end_addr) {
Ok(()) => 0,
Err(e) => e.get(),
}
}
/// Write to a page on the flash chip.
///
/// # Safety
///
/// Will program the given page. Pass a valid page address, and a
/// valid pointer to at least `size` bytes of data.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn ProgramPage(addr: u32, size: u32, data: *const u8) -> u32 {
if !_IS_INIT {
return 1;
}
let this = &mut *_ALGO_INSTANCE.as_mut_ptr();
match <$type as FlashAlgo>::program_page(this, addr, size, data) {
Ok(()) => 0,
Err(e) => e.get(),
}
}
};
}