Files
Upsilon/ion/src/device/flash.cpp
Romain Goyet 7851aa6fff [ion/device] Remove useless delays in the Flash operations
The datasheet advises to wait for BSY to be cleared before performing
any operation on the Flash. That being said, in the only two cases where
BSY could be set in the first place (writing to or erasing the flash),
we already wait for it to be cleared. There's therefore no need to
double check it afterwards.
2018-05-09 11:03:01 +02:00

104 lines
2.3 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);
}
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();
}
}
}
}