mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 22:00:28 +01:00
110 lines
2.4 KiB
C++
110 lines
2.4 KiB
C++
#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);
|
|
|
|
// Wait until the Flash is ready
|
|
wait();
|
|
}
|
|
|
|
static void close() {
|
|
// Wait for pending Flash operations to complete
|
|
wait();
|
|
|
|
// 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();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|