mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[usb | recovery] Make the code works
This commit is contained in:
@@ -123,7 +123,7 @@ void init() {
|
||||
initClocks();
|
||||
|
||||
// The bootloader leaves its own after flashing
|
||||
// SYSCFG.MEMRMP()->setMEM_MODE(SYSCFG::MEMRMP::MemMode::MainFlashmemory);
|
||||
//SYSCFG.MEMRMP()->setMEM_MODE(SYSCFG::MEMRMP::MemMode::MainFlashmemory);
|
||||
// Ensure right location of interrupt vectors
|
||||
CORTEX.VTOR()->setVTOR((void*)&InitialisationVector);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ extern "C" {
|
||||
void bf_abort();
|
||||
void uf_abort();
|
||||
void nmi_abort();
|
||||
// Here and below, we mean init the abort handler, not the opposite
|
||||
// Here and below, we are doing operations on the abort handler, not the opposite
|
||||
void abort_init();
|
||||
void abort_core(const char *);
|
||||
void abort_screen(const char *);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "isr.h"
|
||||
#include <drivers/battery.h>
|
||||
#include <drivers/cache.h>
|
||||
#include <drivers/external_flash.h>
|
||||
@@ -28,20 +27,20 @@
|
||||
typedef void (*cxx_constructor)();
|
||||
|
||||
extern "C" {
|
||||
extern char _data_section_start_flash;
|
||||
extern char _data_section_start_ram;
|
||||
extern char _data_section_end_ram;
|
||||
extern char _bss_section_start_ram;
|
||||
extern char _bss_section_end_ram;
|
||||
extern cxx_constructor _init_array_start;
|
||||
extern cxx_constructor _init_array_end;
|
||||
extern char _data_section_start_flash;
|
||||
extern char _data_section_start_ram;
|
||||
extern char _data_section_end_ram;
|
||||
extern char _bss_section_start_ram;
|
||||
extern char _bss_section_end_ram;
|
||||
extern cxx_constructor _init_array_start;
|
||||
extern cxx_constructor _init_array_end;
|
||||
}
|
||||
|
||||
/* In order to ensure that this method is execute from the external flash, we
|
||||
* forbid inlining it.*/
|
||||
|
||||
static void __attribute__((noinline)) external_flash_start() {
|
||||
/* Init the peripherals. We do not initialize the backlight in case there is
|
||||
/* Init the peripherals. We do not initialize the backlight in case there is
|
||||
* an on boarding app: indeed, we don't want the user to see the LCD tests
|
||||
* happening during the on boarding app. The backlight will be initialized
|
||||
* after the Power-On Self-Test if there is one or before switching to the
|
||||
@@ -69,155 +68,7 @@ static void __attribute__((noinline)) external_flash_start() {
|
||||
* internal flash to the external flash. */
|
||||
|
||||
static void __attribute__((noinline)) jump_to_external_flash() {
|
||||
external_flash_start();
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_init() {
|
||||
Ion::Device::Board::shutdownPeripherals(true);
|
||||
Ion::Device::Board::initPeripherals(false);
|
||||
Ion::Timing::msleep(100);
|
||||
Ion::Backlight::init();
|
||||
Ion::LED::setColor(KDColorRed);
|
||||
Ion::Backlight::setBrightness(180);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_economy() {
|
||||
int brightness = Ion::Backlight::brightness();
|
||||
bool plugged = Ion::USB::isPlugged();
|
||||
while (brightness > 0) {
|
||||
brightness--;
|
||||
Ion::Backlight::setBrightness(brightness);
|
||||
Ion::Timing::msleep(50);
|
||||
if(plugged || (!plugged && Ion::USB::isPlugged())){
|
||||
Ion::Backlight::setBrightness(180);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Ion::Backlight::shutdown();
|
||||
while (1) {
|
||||
Ion::Device::Power::sleepConfiguration();
|
||||
Ion::Device::WakeUp::onUSBPlugging();
|
||||
Ion::Device::WakeUp::onChargingEvent();
|
||||
Ion::Device::Power::internalFlashSuspend(true);
|
||||
if (!plugged && Ion::USB::isPlugged()) {
|
||||
break;
|
||||
}
|
||||
plugged = Ion::USB::isPlugged();
|
||||
};
|
||||
Ion::Device::Board::setStandardFrequency(Ion::Device::Board::Frequency::High);
|
||||
Ion::Backlight::init();
|
||||
Ion::Backlight::setBrightness(180);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_sleeping() {
|
||||
if (Ion::Battery::level() != Ion::Battery::Charge::EMPTY) {
|
||||
return;
|
||||
}
|
||||
// we don't use Ion::Power::suspend because we don't want to move the exam buffer into the internal
|
||||
Ion::Device::Board::shutdownPeripherals(true);
|
||||
bool plugged = Ion::USB::isPlugged();
|
||||
while (1) {
|
||||
Ion::Device::Battery::initGPIO();
|
||||
Ion::Device::USB::initGPIO();
|
||||
Ion::Device::LED::init();
|
||||
Ion::Device::Power::sleepConfiguration();
|
||||
Ion::Device::Board::shutdownPeripherals(true);
|
||||
Ion::Device::WakeUp::onUSBPlugging();
|
||||
Ion::Device::WakeUp::onChargingEvent();
|
||||
Ion::Device::Power::internalFlashSuspend(true);
|
||||
Ion::Device::USB::initGPIO();
|
||||
if (!plugged && Ion::USB::isPlugged()) {
|
||||
break;
|
||||
}
|
||||
plugged = Ion::USB::isPlugged();
|
||||
}
|
||||
Ion::Device::Board::setStandardFrequency(Ion::Device::Board::Frequency::High);
|
||||
abort_init();
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_core(const char * text) {
|
||||
Ion::Timing::msleep(100);
|
||||
int counting;
|
||||
while (true) {
|
||||
counting = 0;
|
||||
if (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
|
||||
abort_sleeping();
|
||||
abort_screen(text);
|
||||
}
|
||||
|
||||
Ion::USB::enable();
|
||||
Ion::Battery::Charge previous_state = Ion::Battery::level();
|
||||
while (!Ion::USB::isEnumerated()) {
|
||||
if (Ion::Battery::level() == Ion::Battery::Charge::LOW) {
|
||||
if (previous_state != Ion::Battery::Charge::LOW) {
|
||||
previous_state = Ion::Battery::Charge::LOW;
|
||||
counting = 0;
|
||||
}
|
||||
Ion::Timing::msleep(500);
|
||||
if (counting >= 20) {
|
||||
abort_sleeping();
|
||||
abort_screen(text);
|
||||
counting = -1;
|
||||
}
|
||||
counting++;
|
||||
|
||||
} else {
|
||||
if (previous_state == Ion::Battery::Charge::LOW) {
|
||||
previous_state = Ion::Battery::level();
|
||||
counting = 0;
|
||||
}
|
||||
Ion::Timing::msleep(100);
|
||||
if (counting >= 300) {
|
||||
abort_economy();
|
||||
counting = -1;
|
||||
}
|
||||
counting++;
|
||||
}
|
||||
}
|
||||
Ion::USB::DFU(false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_screen(const char * text){
|
||||
KDRect screen = KDRect(0, 0, Ion::Display::Width, Ion::Display::Height);
|
||||
Ion::Display::pushRectUniform(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), KDColor::RGB24(0xffffff));
|
||||
KDContext* ctx = KDIonContext::sharedContext();
|
||||
ctx->setOrigin(KDPointZero);
|
||||
ctx->setClippingRect(screen);
|
||||
ctx->drawString("UPSILON CRASH", KDPoint(90, 10), KDFont::LargeFont, KDColorRed, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("An error occurred", KDPoint(10, 30), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("If you have some important data, please", KDPoint(10, 45), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("use bit.ly/upsiBackup to backup them.", KDPoint(10, 60), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("YOU WILL LOSE ALL YOUR DATA", KDPoint(10, 85), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("→ You can try to reboot by presssing the", KDPoint(10, 110), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("reset button at the back of the calculator", KDPoint(10, 125), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("→ If Upsilon keeps crashing, you can connect", KDPoint(10, 140), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("the calculator to a computer or a phone", KDPoint(10, 160), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString("and try to reinstall Upsilon", KDPoint(10, 175), KDFont::SmallFont, KDColorBlack, KDColor::RGB24(0xffffff));
|
||||
ctx->drawString(text, KDPoint(220, 200), KDFont::SmallFont, KDColorRed, KDColor::RGB24(0xffffff));
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort() {
|
||||
abort_init();
|
||||
abort_screen("HARDFAULT");
|
||||
abort_core("HARDFAULT");
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) nmi_abort() {
|
||||
abort_init();
|
||||
abort_screen("NMIFAULT");
|
||||
abort_core("NMIFAULT");
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) bf_abort() {
|
||||
abort_init();
|
||||
abort_screen("BUSFAULT");
|
||||
abort_core("BUSFAULT");
|
||||
}
|
||||
void __attribute__((noinline)) uf_abort() {
|
||||
abort_init();
|
||||
abort_screen("USAGEFAULT");
|
||||
abort_core("USAGEFAULT");
|
||||
external_flash_start();
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) abort_init() {
|
||||
@@ -261,10 +112,10 @@ void __attribute__((noinline)) abort_sleeping() {
|
||||
if (Ion::Battery::level() != Ion::Battery::Charge::EMPTY) {
|
||||
return;
|
||||
}
|
||||
// We don't use Ion::Power::suspend because we don't want to move the exam buffer into the internal
|
||||
// we don't use Ion::Power::suspend because we don't want to move the exam buffer into the internal
|
||||
Ion::Device::Board::shutdownPeripherals(true);
|
||||
bool plugged = Ion::USB::isPlugged();
|
||||
while (true) {
|
||||
while (1) {
|
||||
Ion::Device::Battery::initGPIO();
|
||||
Ion::Device::USB::initGPIO();
|
||||
Ion::Device::LED::init();
|
||||
@@ -373,27 +224,27 @@ void __attribute__((noinline)) uf_abort() {
|
||||
* (just in case 'start' was to be called from the external flash). */
|
||||
|
||||
void __attribute__((noinline)) start() {
|
||||
/* This is where execution starts after reset.
|
||||
/* This is where execution starts after reset.
|
||||
* Many things are not initialized yet so the code here has to pay attention. */
|
||||
|
||||
/* Copy data section to RAM
|
||||
/* Copy data section to RAM
|
||||
* The data section is R/W but its initialization value matters. It's stored
|
||||
* in Flash, but linked as if it were in RAM. Now's our opportunity to copy
|
||||
* it. Note that until then the data section (e.g. global variables) contains
|
||||
* garbage values and should not be used. */
|
||||
size_t dataSectionLength = (&_data_section_end_ram - &_data_section_start_ram);
|
||||
memcpy(&_data_section_start_ram, &_data_section_start_flash, dataSectionLength);
|
||||
size_t dataSectionLength = (&_data_section_end_ram - &_data_section_start_ram);
|
||||
memcpy(&_data_section_start_ram, &_data_section_start_flash, dataSectionLength);
|
||||
|
||||
/* Zero-out the bss section in RAM
|
||||
/* Zero-out the bss section in RAM
|
||||
* Until we do, any uninitialized global variable will be unusable. */
|
||||
size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram);
|
||||
memset(&_bss_section_start_ram, 0, bssSectionLength);
|
||||
size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram);
|
||||
memset(&_bss_section_start_ram, 0, bssSectionLength);
|
||||
|
||||
/* Initialize the FPU as early as possible.
|
||||
/* Initialize the FPU as early as possible.
|
||||
* For example, static C++ objects are very likely to manipulate float values */
|
||||
Ion::Device::Board::initFPU();
|
||||
Ion::Device::Board::initFPU();
|
||||
|
||||
/* Call static C++ object constructors
|
||||
/* Call static C++ object constructors
|
||||
* The C++ compiler creates an initialization function for each static object.
|
||||
* The linker then stores the address of each of those functions consecutively
|
||||
* between _init_array_start and _init_array_end. So to initialize all C++
|
||||
@@ -405,26 +256,26 @@ void __attribute__((noinline)) start() {
|
||||
(*c)();
|
||||
}
|
||||
#else
|
||||
/* In practice, static initialized objects are a terrible idea. Since the init
|
||||
/* In practice, static initialized objects are a terrible idea. Since the init
|
||||
* order is not specified, most often than not this yields the dreaded static
|
||||
* init order fiasco. How about bypassing the issue altogether? */
|
||||
if (&_init_array_start != &_init_array_end) {
|
||||
abort();
|
||||
}
|
||||
if (&_init_array_start != &_init_array_end) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
Ion::Device::Board::init();
|
||||
Ion::Device::Board::init();
|
||||
|
||||
/* At this point, we initialized clocks and the external flash but no other
|
||||
/* At this point, we initialized clocks and the external flash but no other
|
||||
* peripherals. */
|
||||
|
||||
jump_to_external_flash();
|
||||
jump_to_external_flash();
|
||||
|
||||
abort();
|
||||
abort();
|
||||
}
|
||||
|
||||
void __attribute__((interrupt, noinline)) isr_systick() {
|
||||
auto t = Ion::Device::Timing::MillisElapsed;
|
||||
t++;
|
||||
Ion::Device::Timing::MillisElapsed = t;
|
||||
auto t = Ion::Device::Timing::MillisElapsed;
|
||||
t++;
|
||||
Ion::Device::Timing::MillisElapsed = t;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
#include <ion/storage.h>
|
||||
#include <ion/timing.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace USB {
|
||||
|
||||
constexpr static uint8_t k_externalMagik[9] = {0x64, 0x6c, 0x31, 0x31, 0x23, 0x39, 0x38, 0x33, 0x35};
|
||||
|
||||
static inline uint32_t minUint32T(uint32_t x, uint32_t y) { return x < y ? x : y; }
|
||||
|
||||
void DFUInterface::StatusData::push(Channel *c) const {
|
||||
@@ -54,7 +57,6 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran
|
||||
if (request->wLength() > 0) {
|
||||
// The request is a "real" download. Compute the writing address.
|
||||
m_writeAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer;
|
||||
|
||||
// Store the received data until we copy it on the flash.
|
||||
memcpy(m_largeBuffer, transferBuffer, *transferBufferLength);
|
||||
m_largeBufferLength = *transferBufferLength;
|
||||
@@ -67,9 +69,6 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer
|
||||
if (request->bRequest() == (uint8_t)DFURequest::GetStatus) {
|
||||
// Do any needed action after the GetStatus request.
|
||||
if (m_state == State::dfuMANIFEST) {
|
||||
if (m_dfuLevel == 1 && m_isFirstExternalFlash && !m_isInternalLocked) {
|
||||
return;
|
||||
}
|
||||
/* If we leave the DFU and reset immediately, dfu-util outputs an error:
|
||||
* "File downloaded successfully
|
||||
* dfu-util: Error during download get_status"
|
||||
@@ -81,7 +80,6 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer
|
||||
// Leave DFU routine: Leave DFU, reset device, jump to application code
|
||||
leaveDFUAndReset();
|
||||
} else if (m_state == State::dfuDNBUSY) {
|
||||
m_state = State::dfuDNBUSY;
|
||||
if (m_largeBufferLength != 0) {
|
||||
// Here, copy the data from the transfer buffer to the flash memory
|
||||
writeOnMemory();
|
||||
@@ -168,7 +166,10 @@ bool DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferB
|
||||
void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength) {
|
||||
assert(transferBufferLength == 5);
|
||||
// Compute the new address but change it after the next getStatus request.
|
||||
m_potentialNewAddressPointer = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24);
|
||||
m_potentialNewAddressPointer = transferBuffer[1]
|
||||
+ (transferBuffer[2] << 8)
|
||||
+ (transferBuffer[3] << 16)
|
||||
+ (transferBuffer[4] << 24);
|
||||
m_state = State::dfuDNLOADSYNC;
|
||||
}
|
||||
|
||||
@@ -198,7 +199,10 @@ void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBuffer
|
||||
// Sector erase
|
||||
assert(transferBufferLength == 5);
|
||||
|
||||
m_eraseAddress = transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24);
|
||||
uint32_t m_eraseAddress = transferBuffer[1]
|
||||
+ (transferBuffer[2] << 8)
|
||||
+ (transferBuffer[3] << 16)
|
||||
+ (transferBuffer[4] << 24);
|
||||
|
||||
m_erasePage = Flash::SectorAtAddress(m_eraseAddress);
|
||||
if (m_erasePage < 0) {
|
||||
@@ -210,13 +214,24 @@ void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBuffer
|
||||
|
||||
void DFUInterface::eraseMemoryIfNeeded() {
|
||||
if (m_erasePage < 0) {
|
||||
// There was no erase waiting.
|
||||
return;
|
||||
}
|
||||
|
||||
willErase();
|
||||
if ((m_eraseAddress >= k_ExternalBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || m_dfuUnlocked) {
|
||||
int32_t order = Flash::SectorAtAddress(m_eraseAddress);
|
||||
Flash::EraseSector(order);
|
||||
|
||||
#if 0 // We don't erase now the flash memory to avoid crash if writing is refused
|
||||
if (m_erasePage == Flash::TotalNumberOfSectors()) {
|
||||
Flash::MassErase();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((m_eraseAddress >= k_externalAppsBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || m_dfuUnlocked) {
|
||||
Flash::EraseSector(m_erasePage);
|
||||
}
|
||||
/* Put an out of range value in m_erasePage to indicate that no erase is
|
||||
* waiting. */
|
||||
m_erasePage = -1;
|
||||
m_state = State::dfuDNLOADIDLE;
|
||||
m_status = Status::OK;
|
||||
m_erasePage = -1;
|
||||
@@ -227,238 +242,67 @@ void DFUInterface::writeOnMemory() {
|
||||
// Write on SRAM
|
||||
// FIXME We should check that we are not overriding the current instructions.
|
||||
memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength);
|
||||
reset_custom_vars(); // On reset les vars car la ram n'a pas de secteur à effacer
|
||||
resetProtectionVariables(); // We can reset the protection variables because update process is finsihed.
|
||||
} else if (Flash::SectorAtAddress(m_writeAddress) >= 0) {
|
||||
if (m_dfuLevel == 2) {
|
||||
if (m_dfuLevel == 2) { // If no-update mode, we throw an error
|
||||
m_largeBufferLength = 0;
|
||||
m_state = State::dfuERROR;
|
||||
m_status = Status::errWRITE;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int current_memory_flashed;
|
||||
if (m_writeAddress >= InternalFlash::Config::StartAddress && m_writeAddress <= InternalFlash::Config::EndAddress) {
|
||||
if (m_isInternalLocked && !m_dfuUnlocked) // On vérifie si l'external a été flash
|
||||
{
|
||||
m_largeBufferLength = 0;
|
||||
m_state = State::dfuERROR;
|
||||
m_status = Status::errTARGET;
|
||||
leaveDFUAndReset(false); // Numworks flash l'internal avant donc on exit pour afficher le message
|
||||
return;
|
||||
}
|
||||
current_memory_flashed = 0;
|
||||
|
||||
//on écrit dans la mémoire interne
|
||||
if (m_isFirstInternalFlash && !m_dfuUnlocked) {
|
||||
m_temp_is_valid = true;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (magik[i] != m_largeBuffer[magik_adrs + i]) {
|
||||
m_temp_is_valid = false;
|
||||
break;
|
||||
|
||||
if (!(m_isTemporaryUnlocked || m_dfuUnlocked)) {
|
||||
if (m_writeAddress >= InternalFlash::Config::StartAddress && m_writeAddress <= InternalFlash::Config::EndAddress) {
|
||||
// We check if the user is autorized to write on the internal flash
|
||||
if (m_haveAlreadyFlashedExternal) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (k_internalMagik[i] != m_largeBuffer[k_internalMagikPointer + i]) {
|
||||
m_largeBufferLength = 0;
|
||||
m_state = State::dfuERROR;
|
||||
m_status = Status::errWRITE;
|
||||
// We don't leave DFU to avoid having only external flashed
|
||||
return;
|
||||
}
|
||||
m_largeBuffer[k_internalMagikPointer + i] = 0; // We reset the buffer to its initial value
|
||||
}
|
||||
}
|
||||
if (!m_temp_is_valid) {
|
||||
else { // All people trying to write on the internal flash before external are considered as not authorized
|
||||
m_largeBufferLength = 0;
|
||||
m_state = State::dfuERROR;
|
||||
m_status = Status::errVERIFY;
|
||||
//leaveDFUAndReset(); On ne leave plus sinon on fait crash la calc si il n'y a que la partie ext.
|
||||
m_status = Status::errTARGET;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
} else {
|
||||
m_isFirstInternalFlash = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current_memory_flashed = 1;
|
||||
// Nous écrivons la partie external os
|
||||
if (m_writeAddress < k_ExternalBorderAddress && m_isFirstExternalFlash && !m_dfuUnlocked) // On vérifie si on installe des apps ext
|
||||
{
|
||||
// if (m_dfuLevel == 1 && m_isInternalLocked) {
|
||||
// m_largeBufferLength = 0;
|
||||
// m_state = State::dfuERROR;
|
||||
// m_status = Status::errTARGET;
|
||||
// return;
|
||||
// }
|
||||
else if (m_writeAddress < k_externalAppsBorderAddress) { // If we are not installing external apps
|
||||
if (m_dfuLevel == 0) {
|
||||
// Partie moche du code parce que je n'arrivais pas à compil avec 3 boucles for sous msys
|
||||
int adress_magik = magik_ext_adrs[0];
|
||||
m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik];
|
||||
m_largeBuffer[adress_magik] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
if (k_externalMagik[i] != m_largeBuffer[k_externalMagikPointer + i]) {
|
||||
m_largeBufferLength = 0;
|
||||
m_state = State::dfuERROR;
|
||||
m_status = Status::errWRITE;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
m_largeBuffer[k_externalMagikPointer + i] = 0; // We reset the buffer to its initial value
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1];
|
||||
m_largeBuffer[adress_magik + 1] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2];
|
||||
m_largeBuffer[adress_magik + 2] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3];
|
||||
m_largeBuffer[adress_magik + 3] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
adress_magik = magik_ext_adrs[1];
|
||||
|
||||
m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik];
|
||||
m_largeBuffer[adress_magik] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 1];
|
||||
m_largeBuffer[adress_magik + 1] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 2];
|
||||
m_largeBuffer[adress_magik + 2] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 3];
|
||||
m_largeBuffer[adress_magik + 3] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
adress_magik = magik_ext_adrs[2];
|
||||
m_temp_is_valid = true;
|
||||
|
||||
m_temp_is_valid = external_magik[0] == m_largeBuffer[adress_magik];
|
||||
m_largeBuffer[adress_magik] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[1] == m_largeBuffer[adress_magik + 1];
|
||||
m_largeBuffer[adress_magik + 1] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[2] == m_largeBuffer[adress_magik + 2];
|
||||
m_largeBuffer[adress_magik + 2] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[3] == m_largeBuffer[adress_magik + 3];
|
||||
m_largeBuffer[adress_magik + 3] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_temp_is_valid = external_magik[4] == m_largeBuffer[adress_magik + 4];
|
||||
m_largeBuffer[adress_magik + 4] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
m_temp_is_valid = external_magik[5] == m_largeBuffer[adress_magik + 5];
|
||||
m_largeBuffer[adress_magik + 5] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
m_temp_is_valid = external_magik[6] == m_largeBuffer[adress_magik + 6];
|
||||
m_largeBuffer[adress_magik + 6] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
m_temp_is_valid = external_magik[7] == m_largeBuffer[adress_magik + 7];
|
||||
m_largeBuffer[adress_magik + 7] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
}
|
||||
m_temp_is_valid = external_magik[8] == m_largeBuffer[adress_magik + 8];
|
||||
m_largeBuffer[adress_magik + 8] = 0xff;
|
||||
|
||||
if (!m_temp_is_valid) {
|
||||
m_largeBufferLength = 0;
|
||||
leaveDFUAndReset(false);
|
||||
return;
|
||||
} else {
|
||||
m_isFirstExternalFlash = false;
|
||||
m_isInternalLocked = false;
|
||||
}
|
||||
} else {
|
||||
m_isFirstExternalFlash = false;
|
||||
m_isInternalLocked = false;
|
||||
m_isTemporaryUnlocked = true; // We can unlock the flash because signature is good
|
||||
}
|
||||
else {
|
||||
m_haveAlreadyFlashedExternal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_last_memoryFlashed >= 0 && current_memory_flashed != m_last_memoryFlashed) {
|
||||
m_last_memoryFlashed = -1;
|
||||
}
|
||||
|
||||
m_erasePage = Flash::SectorAtAddress(m_writeAddress);
|
||||
int pageToErase = Flash::SectorAtAddress(m_writeAddress);
|
||||
|
||||
//On vérifie qu'on a pas déjà effacé le secteur et si ce n'est pas un secteur external déjà effacé
|
||||
if ((m_last_memoryFlashed < 0 || m_erasePage != m_lastPageErased) && m_writeAddress < k_ExternalBorderAddress && !m_dfuUnlocked) {
|
||||
Flash::EraseSector(m_erasePage);
|
||||
m_last_memoryFlashed = current_memory_flashed;
|
||||
if ((m_lastErasedPage == -1 || pageToErase != m_lastErasedPage) && m_writeAddress < k_externalAppsBorderAddress && !m_dfuUnlocked) {
|
||||
Flash::EraseSector(pageToErase);
|
||||
m_lastErasedPage = pageToErase;
|
||||
}
|
||||
|
||||
m_lastPageErased = m_erasePage;
|
||||
m_erasePage = -1;
|
||||
|
||||
Ion::Timing::msleep(1);
|
||||
Flash::WriteMemory(reinterpret_cast<uint8_t *>(m_writeAddress), m_largeBuffer, m_largeBufferLength);
|
||||
} else {
|
||||
// Invalid write address
|
||||
@@ -467,6 +311,7 @@ void DFUInterface::writeOnMemory() {
|
||||
m_status = Status::errTARGET;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the buffer length
|
||||
m_largeBufferLength = 0;
|
||||
// Change the interface state and status
|
||||
@@ -505,14 +350,11 @@ bool DFUInterface::dfuAbort(uint16_t *transferBufferLength) {
|
||||
}
|
||||
|
||||
void DFUInterface::leaveDFUAndReset(bool do_reset) {
|
||||
reset_custom_vars();
|
||||
m_isInternalLocked = true;
|
||||
m_isFirstInternalFlash = true;
|
||||
m_isFirstExternalFlash = true;
|
||||
resetProtectionVariables();
|
||||
m_device->setResetOnDisconnect(do_reset);
|
||||
m_device->detach();
|
||||
}
|
||||
|
||||
} // namespace USB
|
||||
} // namespace Device
|
||||
} // namespace Ion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,10 +148,10 @@ private:
|
||||
constexpr static uint32_t k_sramEndAddress = 0x20040000;
|
||||
constexpr static uint32_t k_externalAppsBorderAddress = 0x90200000;
|
||||
|
||||
const static int k_internalMagikPointer = 0x1C4;
|
||||
constexpr static int k_internalMagikPointer = 0x1C4;
|
||||
constexpr static int k_externalMagikPointer = 0x44F;
|
||||
constexpr static uint8_t k_internalMagik[4] = {0xF0, 0x0D, 0xC0, 0xDE};
|
||||
constexpr static uint8_t k_externalMagik[9] = {0x64, 0x6c, 0x31, 0x31, 0x23, 0x39, 0x38, 0x33, 0x35};
|
||||
constexpr static uint8_t k_externalMagik[4] = {0x32, 0x30, 0x30, 0x36};
|
||||
|
||||
// Download and upload
|
||||
bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength);
|
||||
|
||||
Reference in New Issue
Block a user