[ion/device] Flash driver handles Internal and external flash

This commit is contained in:
Léa Saviot
2019-12-10 11:40:54 +01:00
committed by EmilieNumworks
parent ebc5843795
commit 762f67d996
12 changed files with 337 additions and 271 deletions

View File

@@ -1,11 +1,11 @@
#ifndef ION_DEVICE_N0100_CONFIG_FLASH_H
#define ION_DEVICE_N0100_CONFIG_FLASH_H
#ifndef ION_DEVICE_N0100_CONFIG_INTERNAL_FLASH_H
#define ION_DEVICE_N0100_CONFIG_INTERNAL_FLASH_H
#include <regs/regs.h>
namespace Ion {
namespace Device {
namespace Flash {
namespace InternalFlash {
namespace Config {
constexpr static uint32_t StartAddress = 0x08000000;

View File

@@ -1,5 +1,5 @@
#include <drivers/reset.h>
#include "config/flash.h"
#include "config/internal_flash.h"
namespace Ion {
namespace Device {
@@ -10,7 +10,7 @@ void coreWhilePlugged() {
* might be plugged in. Doing a full core reset would result in the device
* entering the ST DFU bootloader. By performing a jump-reset, we mimic the
* core reset without entering ST bootloader.*/
jump(Flash::Config::StartAddress);
jump(InternalFlash::Config::StartAddress);
}
}

View File

@@ -1,11 +1,11 @@
#ifndef ION_DEVICE_N0110_CONFIG_FLASH_H
#define ION_DEVICE_N0110_CONFIG_FLASH_H
#ifndef ION_DEVICE_N0110_CONFIG_INTERNAL_FLASH_H
#define ION_DEVICE_N0110_CONFIG_INTERNAL_FLASH_H
#include <regs/regs.h>
namespace Ion {
namespace Device {
namespace Flash {
namespace InternalFlash {
namespace Config {
constexpr static uint32_t StartAddress = 0x08000000;

View File

@@ -9,6 +9,7 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
exam_mode.cpp \
external_flash.cpp \
flash.cpp \
internal_flash.cpp \
keyboard.cpp \
led.cpp \
power.cpp\

View File

@@ -1,5 +1,6 @@
#include <ion/exam_mode.h>
#include "flash.h"
#include <assert.h>
namespace Ion {
namespace ExamMode {

View File

@@ -1,253 +1,53 @@
#include "flash.h"
#include <drivers/cache.h>
#include <drivers/config/flash.h>
#include "external_flash.h"
#include "internal_flash.h"
#include <drivers/config/internal_flash.h>
#include <drivers/config/external_flash.h>
#include <assert.h>
namespace Ion {
namespace Device {
namespace Flash {
using namespace Regs;
static inline void wait() {
/* Issue a DSB instruction to guarantee the completion of a previous access
* to FLASH_CR register or data write operation. (RM0431) */
Cache::dsb();
// 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() {
// Clear error flags
class FLASH::SR sr(0);
// Error flags are cleared by writing 1
sr.setERSERR(true);
sr.setPGPERR(true);
sr.setPGAERR(true);
sr.setWRPERR(true);
sr.setEOP(true);
FLASH.SR()->set(sr);
// 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 REGS_FLASH_CONFIG_ART
if (FLASH.ACR()->getARTEN()) {
FLASH.ACR()->setARTEN(false);
FLASH.ACR()->setARTRST(true);
FLASH.ACR()->setARTRST(false);
FLASH.ACR()->setARTEN(true);
}
#else
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);
}
#endif
}
// Compile-time log2
static inline constexpr size_t clog2(size_t input) {
return (input == 1) ? 0 : clog2(input/2)+1;
}
// Align a pointer to a given type's boundaries
// Returns a value that is lower or equal to input
template <typename T>
static inline T * align(void * input) {
size_t k = clog2(sizeof(T));
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(input) & ~((1<<k) - 1));
}
template <typename T>
static inline T eat(void * ptr) {
T * pointer = *reinterpret_cast<T **>(ptr);
T result = *pointer;
*reinterpret_cast<T **>(ptr) = pointer+1;
return result;
}
static inline ptrdiff_t byte_offset(void * p1, void * p2) {
return reinterpret_cast<uint8_t *>(p2) - reinterpret_cast<uint8_t *>(p1);
}
template <typename T>
static inline T min(T i, T j) {
return (i<j) ? i : j;
}
static void flash_memcpy(uint8_t * destination, uint8_t * source, size_t length) {
/* RM0402 3.5.4
* It is not allowed to program data to the Flash memory that would cross the
* 128-bit row boundary. In such a case, the write operation is not performed
* and a program alignment error flag (PGAERR) is set in the FLASH_SR
* register.
* The write access type (byte, half-word, word or double word) must
* correspond to the type of parallelism chosen (x8, x16, x32 or x64). If not,
* the write operation is not performed and a program parallelism error flag
* (PGPERR) is set in the FLASH_SR register. */
static_assert(
sizeof(MemoryAccessType) == 1 ||
sizeof(MemoryAccessType) == 2 ||
sizeof(MemoryAccessType) == 4 ||
sizeof(MemoryAccessType) == 8,
"Invalid MemoryAccessType");
/* So we may only perform memory writes with pointers of type MemoryAccessType
* and we must make sure to never cross 128 bit boundaries. This second
* requirement is satisfied iif the pointers are aligned on MemoryAccessType
* boundaries.
* Long story short: we want to perform writes to aligned(MemoryAccessType *).
*/
/* Step 1 - Copy a header if needed
* We start by copying a Header, whose size is MemoryAccessType, to bring us
* back on aligned tracks.
*
* _AlignedDst _DESTINATION
* | |
* --+--------+--------+--------+--------+--------+--------+--
* | || | | | || |
*---+--------+--------+--------+--------+--------+--------+--
* |<------------ Header ------------->|
* |-- HeaderDelta ->|
*/
MemoryAccessType * alignedDestination = align<MemoryAccessType>(destination);
ptrdiff_t headerDelta = byte_offset(alignedDestination, destination);
assert(headerDelta >= 0 && headerDelta < static_cast<ptrdiff_t>(sizeof(MemoryAccessType)));
if (headerDelta > 0) {
// At this point, alignedDestination < destination
// We'll then retrieve the current value at alignedDestination, fill it with
// bytes from source, and write it back at alignedDestination.
// First, retrieve the current value at alignedDestination
MemoryAccessType header = *alignedDestination;
// Then copy headerLength bytes from source and put them in the header
uint8_t * headerStart = reinterpret_cast<uint8_t *>(&header);
// Here's where source data shall start being copied in the header
uint8_t * headerDataStart = headerStart + headerDelta;
// And here's where it should end
uint8_t * headerDataEnd = min<uint8_t *>(
headerStart + sizeof(MemoryAccessType), // Either at the end of the header
headerDataStart + length // or whenever src runs out of data
);
for (uint8_t * h = headerDataStart; h<headerDataEnd; h++) {
*h = eat<uint8_t>(&source);
}
// Then eventually write the header back into the aligned destination
*alignedDestination++ = header;
wait();
}
/* Step 2 - Copy the bulk of the data
* At this point, we can use aligned MemoryAccessType pointers. */
MemoryAccessType * lastAlignedDestination = align<MemoryAccessType>(destination + length);
while (alignedDestination < lastAlignedDestination) {
*alignedDestination++ = eat<MemoryAccessType>(&source);
wait();
}
/* Step 3 - Copy a footer if needed
* Some unaligned data can be pending at the end. Let's take care of it like
* we did for the header.
*
* _alignedDst _Destination+length
* | |
* --+--------+--------+--------+--------+--------+--------+--
* | || | | | || |
*---+--------+--------+--------+--------+--------+--------+--
* |<------------ Footer ------------->|
* |- footerLength ->|
*/
ptrdiff_t footerLength = byte_offset(alignedDestination, destination + length);
assert(footerLength < static_cast<ptrdiff_t>(sizeof(MemoryAccessType)));
if (footerLength > 0) {
assert(alignedDestination == lastAlignedDestination);
// First, retrieve the current value at alignedDestination
MemoryAccessType footer = *alignedDestination;
/* Then copy footerLength bytes from source and put them at the beginning of
* the footer */
uint8_t * footerPointer = reinterpret_cast<uint8_t *>(&footer);
for (ptrdiff_t i=0; i<footerLength; i++) {
footerPointer[i] = eat<uint8_t>(&source);
}
// Then eventually write the footer back into the aligned destination
*alignedDestination = footer;
wait();
}
int TotalNumberOfSectors() {
return InternalFlash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors;
}
int SectorAtAddress(uint32_t address) {
for (int i = 0; i < Config::NumberOfSectors; i++) {
if (address >= Config::SectorAddresses[i] && address < Config::SectorAddresses[i+1]) {
return i;
}
if (address >= InternalFlash::Config::StartAddress
&& address <= InternalFlash::Config::EndAddress)
{
return InternalFlash::SectorAtAddress(address);
}
if (address >= ExternalFlash::Config::StartAddress
&& address <= ExternalFlash::Config::EndAddress)
{
return InternalFlash::Config::NumberOfSectors + ExternalFlash::SectorAtAddress(address - ExternalFlash::Config::StartAddress);
}
return -1;
}
void MassErase() {
open();
FLASH.CR()->setMER(true);
FLASH.CR()->setSTRT(true);
wait();
FLASH.CR()->setMER(false);
close();
InternalFlash::MassErase();
ExternalFlash::MassErase();
}
void EraseSector(int i) {
assert(i >= 0 && i < Config::NumberOfSectors);
open();
FLASH.CR()->setSNB(i);
FLASH.CR()->setSER(true);
FLASH.CR()->setSTRT(true);
wait();
FLASH.CR()->setSNB(0);
FLASH.CR()->setSER(false);
close();
assert(i >= 0 && i < TotalNumberOfSectors());
if (i < InternalFlash::Config::NumberOfSectors) {
InternalFlash::EraseSector(i);
} else {
ExternalFlash::EraseSector(i - InternalFlash::Config::NumberOfSectors);
}
}
void WriteMemory(uint8_t * destination, uint8_t * source, size_t length) {
open();
FLASH.CR()->setPG(true);
flash_memcpy(destination, source, length);
FLASH.CR()->setPG(false);
close();
assert(SectorAtAddress((uint32_t)destination) >= 0);
if (SectorAtAddress((uint32_t)destination) < InternalFlash::Config::NumberOfSectors) {
InternalFlash::WriteMemory(destination, source, length);
} else {
ExternalFlash::WriteMemory(destination - ExternalFlash::Config::StartAddress, source, length);
}
}
}

View File

@@ -2,24 +2,19 @@
#define ION_DEVICE_SHARED_FLASH_H
#include <stddef.h>
#include <regs/regs.h>
#include <stdint.h>
namespace Ion {
namespace Device {
namespace Flash {
void MassErase();
int TotalNumberOfSectors();
int SectorAtAddress(uint32_t address);
void MassErase();
void EraseSector(int i);
void WriteMemory(uint8_t * destination, uint8_t * source, size_t length);
/* The Device is powered by a 2.8V LDO. This allows us to perform writes to the
* Flash 32 bits at once. */
constexpr Regs::FLASH::CR::PSIZE MemoryAccessWidth = Regs::FLASH::CR::PSIZE::X32;
typedef uint32_t MemoryAccessType;
}
}
}

View File

@@ -0,0 +1,256 @@
#include "internal_flash.h"
#include <drivers/cache.h>
#include <drivers/config/internal_flash.h>
#include <assert.h>
namespace Ion {
namespace Device {
namespace InternalFlash {
using namespace Regs;
static inline void wait() {
/* Issue a DSB instruction to guarantee the completion of a previous access
* to FLASH_CR register or data write operation. (RM0431) */
Cache::dsb();
// 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() {
// Clear error flags
class FLASH::SR sr(0);
// Error flags are cleared by writing 1
sr.setERSERR(true);
sr.setPGPERR(true);
sr.setPGAERR(true);
sr.setWRPERR(true);
sr.setEOP(true);
FLASH.SR()->set(sr);
// 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 REGS_FLASH_CONFIG_ART
if (FLASH.ACR()->getARTEN()) {
FLASH.ACR()->setARTEN(false);
FLASH.ACR()->setARTRST(true);
FLASH.ACR()->setARTRST(false);
FLASH.ACR()->setARTEN(true);
}
#else
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);
}
#endif
}
// Compile-time log2
static inline constexpr size_t clog2(size_t input) {
return (input == 1) ? 0 : clog2(input/2)+1;
}
// Align a pointer to a given type's boundaries
// Returns a value that is lower or equal to input
template <typename T>
static inline T * align(void * input) {
size_t k = clog2(sizeof(T));
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(input) & ~((1<<k) - 1));
}
template <typename T>
static inline T eat(void * ptr) {
T * pointer = *reinterpret_cast<T **>(ptr);
T result = *pointer;
*reinterpret_cast<T **>(ptr) = pointer+1;
return result;
}
static inline ptrdiff_t byte_offset(void * p1, void * p2) {
return reinterpret_cast<uint8_t *>(p2) - reinterpret_cast<uint8_t *>(p1);
}
template <typename T>
static inline T min(T i, T j) {
return (i<j) ? i : j;
}
static void flash_memcpy(uint8_t * destination, uint8_t * source, size_t length) {
/* RM0402 3.5.4
* It is not allowed to program data to the Flash memory that would cross the
* 128-bit row boundary. In such a case, the write operation is not performed
* and a program alignment error flag (PGAERR) is set in the FLASH_SR
* register.
* The write access type (byte, half-word, word or double word) must
* correspond to the type of parallelism chosen (x8, x16, x32 or x64). If not,
* the write operation is not performed and a program parallelism error flag
* (PGPERR) is set in the FLASH_SR register. */
static_assert(
sizeof(MemoryAccessType) == 1 ||
sizeof(MemoryAccessType) == 2 ||
sizeof(MemoryAccessType) == 4 ||
sizeof(MemoryAccessType) == 8,
"Invalid MemoryAccessType");
/* So we may only perform memory writes with pointers of type MemoryAccessType
* and we must make sure to never cross 128 bit boundaries. This second
* requirement is satisfied iif the pointers are aligned on MemoryAccessType
* boundaries.
* Long story short: we want to perform writes to aligned(MemoryAccessType *).
*/
/* Step 1 - Copy a header if needed
* We start by copying a Header, whose size is MemoryAccessType, to bring us
* back on aligned tracks.
*
* _AlignedDst _DESTINATION
* | |
* --+--------+--------+--------+--------+--------+--------+--
* | || | | | || |
*---+--------+--------+--------+--------+--------+--------+--
* |<------------ Header ------------->|
* |-- HeaderDelta ->|
*/
MemoryAccessType * alignedDestination = align<MemoryAccessType>(destination);
ptrdiff_t headerDelta = byte_offset(alignedDestination, destination);
assert(headerDelta >= 0 && headerDelta < static_cast<ptrdiff_t>(sizeof(MemoryAccessType)));
if (headerDelta > 0) {
// At this point, alignedDestination < destination
// We'll then retrieve the current value at alignedDestination, fill it with
// bytes from source, and write it back at alignedDestination.
// First, retrieve the current value at alignedDestination
MemoryAccessType header = *alignedDestination;
// Then copy headerLength bytes from source and put them in the header
uint8_t * headerStart = reinterpret_cast<uint8_t *>(&header);
// Here's where source data shall start being copied in the header
uint8_t * headerDataStart = headerStart + headerDelta;
// And here's where it should end
uint8_t * headerDataEnd = min<uint8_t *>(
headerStart + sizeof(MemoryAccessType), // Either at the end of the header
headerDataStart + length // or whenever src runs out of data
);
for (uint8_t * h = headerDataStart; h<headerDataEnd; h++) {
*h = eat<uint8_t>(&source);
}
// Then eventually write the header back into the aligned destination
*alignedDestination++ = header;
wait();
}
/* Step 2 - Copy the bulk of the data
* At this point, we can use aligned MemoryAccessType pointers. */
MemoryAccessType * lastAlignedDestination = align<MemoryAccessType>(destination + length);
while (alignedDestination < lastAlignedDestination) {
*alignedDestination++ = eat<MemoryAccessType>(&source);
wait();
}
/* Step 3 - Copy a footer if needed
* Some unaligned data can be pending at the end. Let's take care of it like
* we did for the header.
*
* _alignedDst _Destination+length
* | |
* --+--------+--------+--------+--------+--------+--------+--
* | || | | | || |
*---+--------+--------+--------+--------+--------+--------+--
* |<------------ Footer ------------->|
* |- footerLength ->|
*/
ptrdiff_t footerLength = byte_offset(alignedDestination, destination + length);
assert(footerLength < static_cast<ptrdiff_t>(sizeof(MemoryAccessType)));
if (footerLength > 0) {
assert(alignedDestination == lastAlignedDestination);
// First, retrieve the current value at alignedDestination
MemoryAccessType footer = *alignedDestination;
/* Then copy footerLength bytes from source and put them at the beginning of
* the footer */
uint8_t * footerPointer = reinterpret_cast<uint8_t *>(&footer);
for (ptrdiff_t i=0; i<footerLength; i++) {
footerPointer[i] = eat<uint8_t>(&source);
}
// Then eventually write the footer back into the aligned destination
*alignedDestination = footer;
wait();
}
}
int SectorAtAddress(uint32_t address) {
for (int i = 0; i < Config::NumberOfSectors; i++) {
if (address >= Config::SectorAddresses[i] && address < Config::SectorAddresses[i+1]) {
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 < Config::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 * destination, uint8_t * source, size_t length) {
open();
FLASH.CR()->setPG(true);
flash_memcpy(destination, source, length);
FLASH.CR()->setPG(false);
close();
}
}
}
}

View File

@@ -0,0 +1,27 @@
#ifndef ION_DEVICE_SHARED_INTERNAL_FLASH_H
#define ION_DEVICE_SHARED_INTERNAL_FLASH_H
#include <stddef.h>
#include <regs/regs.h>
namespace Ion {
namespace Device {
namespace InternalFlash {
void MassErase();
int SectorAtAddress(uint32_t address);
void EraseSector(int i);
void WriteMemory(uint8_t * destination, uint8_t * source, size_t length);
/* The Device is powered by a 2.8V LDO. This allows us to perform writes to the
* Flash 32 bits at once. */
constexpr Regs::FLASH::CR::PSIZE MemoryAccessWidth = Regs::FLASH::CR::PSIZE::X32;
typedef uint32_t MemoryAccessType;
}
}
}
#endif

View File

@@ -55,6 +55,7 @@ dfu_src += $(addprefix ion/src/device/shared/drivers/, \
events_keyboard_platform.cpp \
external_flash.cpp \
flash.cpp \
internal_flash.cpp \
keyboard.cpp \
led.cpp \
power.cpp\

View File

@@ -1,18 +1,12 @@
#include "dfu_interface.h"
#include <drivers/config/external_flash.h>
#include <string.h>
#include <drivers/flash.h>
#include <drivers/external_flash.h>
#include <drivers/config/flash.h>
#include <drivers/config/external_flash.h>
#include <ion/timing.h>
namespace Ion {
namespace Device {
namespace USB {
using namespace Ion::Device::Regs;
static inline uint32_t minUint32T(uint32_t x, uint32_t y) { return x < y ? x : y; }
void DFUInterface::StatusData::push(Channel * c) const {
@@ -188,7 +182,7 @@ void DFUInterface::eraseCommand(uint8_t * transferBuffer, uint16_t transferBuffe
if (transferBufferLength == 1) {
// Mass erase
m_erasePage = Flash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors;
m_erasePage = Flash::TotalNumberOfSectors();
return;
}
@@ -200,11 +194,8 @@ void DFUInterface::eraseCommand(uint8_t * transferBuffer, uint16_t transferBuffe
+ (transferBuffer[3] << 16)
+ (transferBuffer[4] << 24);
if (eraseAddress >= Flash::Config::StartAddress && eraseAddress <= Flash::Config::EndAddress) {
m_erasePage = Flash::SectorAtAddress(eraseAddress);
} else if (eraseAddress >= ExternalFlash::Config::StartAddress && eraseAddress <= ExternalFlash::Config::EndAddress) {
m_erasePage = Flash::Config::NumberOfSectors + ExternalFlash::SectorAtAddress(eraseAddress - ExternalFlash::Config::StartAddress);
} else {
m_erasePage = Flash::SectorAtAddress(eraseAddress);
if (m_erasePage < 0) {
// Unrecognized sector
m_state = State::dfuERROR;
m_status = Status::errTARGET;
@@ -218,13 +209,10 @@ void DFUInterface::eraseMemoryIfNeeded() {
return;
}
if (m_erasePage == Flash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors) {
if (m_erasePage == Flash::TotalNumberOfSectors()) {
Flash::MassErase();
ExternalFlash::MassErase();
} else if (m_erasePage < Flash::Config::NumberOfSectors) {
Flash::EraseSector(m_erasePage);
} else {
ExternalFlash::EraseSector(m_erasePage - Flash::Config::NumberOfSectors);
Flash::EraseSector(m_erasePage);
}
/* Put an out of range value in m_erasePage to indicate that no erase is
@@ -235,15 +223,12 @@ void DFUInterface::eraseMemoryIfNeeded() {
}
void DFUInterface::writeOnMemory() {
if (m_writeAddress >= Flash::Config::StartAddress && m_writeAddress <= Flash::Config::EndAddress) {
// Write to the Flash memory
Flash::WriteMemory(reinterpret_cast<uint8_t *>(m_writeAddress), m_largeBuffer, m_largeBufferLength);
} else if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) {
if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) {
// Write on SRAM
// FIXME We should check that we are not overriding the current instructions.
memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength);
} else if (m_writeAddress >= ExternalFlash::Config::StartAddress && m_writeAddress <= ExternalFlash::Config::EndAddress) {
ExternalFlash::WriteMemory(reinterpret_cast<uint8_t *>(m_writeAddress) - ExternalFlash::Config::StartAddress, m_largeBuffer, m_largeBufferLength);
} else if (Flash::SectorAtAddress(m_writeAddress) >= 0) {
Flash::WriteMemory(reinterpret_cast<uint8_t *>(m_writeAddress), m_largeBuffer, m_largeBufferLength);
} else {
// Invalid write address
m_largeBufferLength = 0;

View File

@@ -1,5 +1,5 @@
#include "device.h"
#include <drivers/config/flash.h>
#include <drivers/config/internal_flash.h>
#include <drivers/reset.h>
#include <regs/regs.h>
@@ -92,7 +92,7 @@ void Device::detach() {
}
void Device::leave(uint32_t leaveAddress) {
if (leaveAddress == Ion::Device::Flash::Config::StartAddress) {
if (leaveAddress == Ion::Device::InternalFlash::Config::StartAddress) {
Ion::Device::Reset::coreWhilePlugged();
} else {
Ion::Device::Reset::jump(leaveAddress);