flash.cpp
2.32 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
#include "flash.h"
#include <assert.h>
namespace Ion {
namespace Flash {
namespace Device {
static inline void wait() {
// Wait for pending Flash operations to complete
while (FLASH.SR()->getBSY()) {
}
}
static void open() {
// Unlock the Flash configuration register if needed
if (FLASH.CR()->getLOCK()) {
FLASH.KEYR()->set(0x45670123);
FLASH.KEYR()->set(0xCDEF89AB);
}
assert(FLASH.CR()->getLOCK() == false);
// Set the programming parallelism
FLASH.CR()->setPSIZE(MemoryAccessWidth);
}
static void close() {
// Lock the Flash configuration register
assert(!FLASH.CR()->getMER());
assert(!FLASH.CR()->getSER());
assert(!FLASH.CR()->getPG());
FLASH.CR()->setLOCK(true);
// Purge Data and instruction cache
if (FLASH.ACR()->getDCEN()) {
FLASH.ACR()->setDCEN(false);
FLASH.ACR()->setDCRST(true);
FLASH.ACR()->setDCRST(false);
FLASH.ACR()->setDCEN(true);
}
if (FLASH.ACR()->getICEN()) {
FLASH.ACR()->setICEN(false);
FLASH.ACR()->setICRST(true);
FLASH.ACR()->setICRST(false);
FLASH.ACR()->setICEN(true);
}
}
static void typed_memcpy(uint8_t * source, uint8_t * destination, size_t length) {
MemoryAccessType * src = reinterpret_cast<MemoryAccessType *>(source);
MemoryAccessType * dst = reinterpret_cast<MemoryAccessType *>(destination);
for (size_t i=0; i<length/sizeof(MemoryAccessType); i++) {
*dst++ = *src++;
}
}
int SectorAtAddress(uint32_t address) {
uint32_t sectorAddresses[NumberOfSectors] = {
0x08000000, 0x08004000, 0x08008000, 0x0800C000,
0x08010000, 0x08020000, 0x08040000, 0x08060000,
0x08080000, 0x080A0000, 0x080C0000, 0x080E0000
};
for (int i=0; i<NumberOfSectors; i++) {
if (sectorAddresses[i] == address) {
return i;
}
}
return -1;
}
void MassErase() {
open();
FLASH.CR()->setMER(true);
FLASH.CR()->setSTRT(true);
wait();
FLASH.CR()->setMER(false);
close();
}
void EraseSector(int i) {
assert(i >= 0 && i < NumberOfSectors);
open();
FLASH.CR()->setSNB(i);
FLASH.CR()->setSER(true);
FLASH.CR()->setSTRT(true);
wait();
FLASH.CR()->setSNB(0);
FLASH.CR()->setSER(false);
close();
}
void WriteMemory(uint8_t * source, uint8_t * destination, size_t length) {
open();
FLASH.CR()->setPG(true);
typed_memcpy(source, destination, length);
wait();
FLASH.CR()->setPG(false);
close();
}
}
}
}