mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Merge remote-tracking branch 'upstream/master' into omega-dev
This commit is contained in:
@@ -245,7 +245,12 @@ bool AppsContainer::switchTo(App::Snapshot * snapshot) {
|
||||
}
|
||||
|
||||
void AppsContainer::run() {
|
||||
window()->setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height));
|
||||
KDRect screenRect = KDRect(0, 0, Ion::Display::Width, Ion::Display::Height);
|
||||
window()->setFrame(screenRect);
|
||||
/* We push a white screen here, because fetching the exam mode takes some time
|
||||
* and it is visible when reflashing a N0100 (there is some noise on the
|
||||
* screen before the logo appears). */
|
||||
Ion::Display::pushRectUniform(screenRect, KDColorWhite);
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) {
|
||||
activateExamMode();
|
||||
}
|
||||
|
||||
32
ion/src/device/n0100/drivers/config/exam_mode.h
Normal file
32
ion/src/device/n0100/drivers/config/exam_mode.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef ION_DEVICE_N0100_CONFIG_EXAM_MODE_H
|
||||
#define ION_DEVICE_N0100_CONFIG_EXAM_MODE_H
|
||||
|
||||
namespace Ion {
|
||||
namespace ExamMode {
|
||||
namespace Config {
|
||||
|
||||
// TODO: factorize the macro with equivalent macro on N110
|
||||
|
||||
#define byte4 0xFF, 0xFF, 0xFF, 0xFF
|
||||
#define byte8 byte4, byte4
|
||||
#define byte16 byte8, byte8
|
||||
#define byte32 byte16, byte16
|
||||
#define byte64 byte32, byte32
|
||||
#define byte128 byte64, byte64
|
||||
#define byte256 byte128, byte128
|
||||
#define byte512 byte256, byte256
|
||||
#define byte1K byte512, byte512
|
||||
#define byte2K byte1K, byte1K
|
||||
#define byte4K byte2K, byte2K
|
||||
#define byte8K byte4K, byte4K
|
||||
#define byte16K byte8K, byte8K
|
||||
|
||||
#define EXAM_BUFFER_CONTENT byte16K
|
||||
|
||||
constexpr static int ExamModeBufferSize = 16*1024;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,16 +9,16 @@
|
||||
* This will let us use shortcuts such as ">FLASH" to ask for a given section to
|
||||
* be stored in Flash. */
|
||||
MEMORY {
|
||||
FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||
FLASH_SECOND_SECTOR (rx) : ORIGIN = (0x08000000 + 16K), LENGTH = 16K
|
||||
FLASH_LAST_SECTORS (rx) : ORIGIN = (0x08000000 + 32K), LENGTH = (1024K - 32K)
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K
|
||||
}
|
||||
|
||||
STACK_SIZE = 32K;
|
||||
FLASH_SECOND_SECTOR_OFFSET = 16K;
|
||||
FLASH_SECOND_SECTOR_SIZE = 16K;
|
||||
|
||||
SECTIONS {
|
||||
.isr_vector_table ORIGIN(FLASH_FIRST_SECTOR) : {
|
||||
.isr_vector_table ORIGIN(FLASH) : {
|
||||
/* When booting, the STM32F412 fetches the content of address 0x0, and
|
||||
* extracts from it various key infos: the initial value of the PC register
|
||||
* (program counter), the initial value of the stack pointer, and various
|
||||
@@ -33,37 +33,39 @@ SECTIONS {
|
||||
* convenient: using function pointers, we can easily point to the service
|
||||
* routine for each interrupt. */
|
||||
KEEP(*(.isr_vector_table))
|
||||
} >FLASH_FIRST_SECTOR
|
||||
} >FLASH
|
||||
|
||||
.header : {
|
||||
KEEP(*(.header))
|
||||
} >FLASH_FIRST_SECTOR
|
||||
ASSERT ((. < ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET), "Error: ISR table or HEADER overflows in the flash sector reserved for the exam mode");
|
||||
} >FLASH
|
||||
|
||||
.exam_mode_persistence ORIGIN(FLASH_SECOND_SECTOR): {
|
||||
_exam_mode_persistence_start = .;
|
||||
.exam_mode_buffer ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET : {
|
||||
_exam_mode_buffer_start = .;
|
||||
KEEP(*(.exam_mode_buffer))
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = (ORIGIN(FLASH_SECOND_SECTOR) + LENGTH(FLASH_SECOND_SECTOR));
|
||||
_exam_mode_persistence_end = .;
|
||||
} >FLASH_SECOND_SECTOR
|
||||
. = ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET + FLASH_SECOND_SECTOR_SIZE;
|
||||
_exam_mode_buffer_end = .;
|
||||
} >FLASH
|
||||
|
||||
.text : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} >FLASH_LAST_SECTORS
|
||||
} >FLASH
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
_init_array_start = .;
|
||||
KEEP (*(.init_array*))
|
||||
_init_array_end = .;
|
||||
} >FLASH_LAST_SECTORS
|
||||
} >FLASH
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >FLASH_LAST_SECTORS
|
||||
} >FLASH
|
||||
|
||||
.data : {
|
||||
/* The data section is written to Flash but linked as if it were in RAM.
|
||||
@@ -84,7 +86,7 @@ SECTIONS {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
_data_section_end_ram = .;
|
||||
} >SRAM AT> FLASH_LAST_SECTORS
|
||||
} >SRAM AT> FLASH
|
||||
|
||||
.bss : {
|
||||
/* The bss section contains data for all uninitialized variables
|
||||
|
||||
@@ -41,6 +41,7 @@ void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disab
|
||||
dcisw.setWAY(w);
|
||||
CORTEX.DCISW()->set(dcisw);
|
||||
}
|
||||
__asm volatile("nop");
|
||||
} while (w-- != 0);
|
||||
} while (sets-- != 0);
|
||||
|
||||
|
||||
30
ion/src/device/n0110/drivers/config/exam_mode.h
Normal file
30
ion/src/device/n0110/drivers/config/exam_mode.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef ION_DEVICE_N0110_CONFIG_EXAM_MODE_H
|
||||
#define ION_DEVICE_N0110_CONFIG_EXAM_MODE_H
|
||||
|
||||
namespace Ion {
|
||||
namespace ExamMode {
|
||||
namespace Config {
|
||||
|
||||
// TODO: factorize the macro with equivalent macro on N100
|
||||
|
||||
#define byte4 0xFF, 0xFF, 0xFF, 0xFF
|
||||
#define byte8 byte4, byte4
|
||||
#define byte16 byte8, byte8
|
||||
#define byte32 byte16, byte16
|
||||
#define byte64 byte32, byte32
|
||||
#define byte128 byte64, byte64
|
||||
#define byte256 byte128, byte128
|
||||
#define byte512 byte256, byte256
|
||||
#define byte1K byte512, byte512
|
||||
#define byte2K byte1K, byte1K
|
||||
#define byte4K byte2K, byte2K
|
||||
|
||||
#define EXAM_BUFFER_CONTENT byte4K
|
||||
|
||||
constexpr static int ExamModeBufferSize = 4*1024;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -12,8 +12,7 @@
|
||||
MEMORY {
|
||||
INTERNAL_FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 64K
|
||||
SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K
|
||||
EXTERNAL_FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x90000000, LENGTH = 4K
|
||||
EXTERNAL_FLASH_NEXT_SECTORS (rx) : ORIGIN = (0x90000000 + 4K), LENGTH = (8M - 4K)
|
||||
EXTERNAL_FLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M
|
||||
/*
|
||||
ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 16K
|
||||
DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
@@ -23,6 +22,7 @@ MEMORY {
|
||||
}
|
||||
|
||||
STACK_SIZE = 32K;
|
||||
FIRST_EXTERNAL_FLASH_SECTOR_SIZE = 4K;
|
||||
|
||||
SECTIONS {
|
||||
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
|
||||
@@ -56,13 +56,6 @@ SECTIONS {
|
||||
*(.text._ZL22jump_to_external_flashv)
|
||||
} >INTERNAL_FLASH
|
||||
|
||||
.exam_mode_persistence ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR): {
|
||||
_exam_mode_persistence_start = .;
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = (ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR) + LENGTH(EXTERNAL_FLASH_FIRST_SECTOR));
|
||||
_exam_mode_persistence_end = .;
|
||||
} >EXTERNAL_FLASH_FIRST_SECTOR
|
||||
|
||||
/* Use boot routine and required dependencies */
|
||||
/* We're relying on symbols being in their own sub-section. On GCC, this is
|
||||
* done with -fdata-sections -ffunction-sections */
|
||||
@@ -123,17 +116,25 @@ SECTIONS {
|
||||
*(.rodata._ZN3Ion6Device5Board4initEv.str1.4)
|
||||
} >INTERNAL_FLASH
|
||||
|
||||
.exam_mode_buffer ORIGIN(EXTERNAL_FLASH) : {
|
||||
_exam_mode_buffer_start = .;
|
||||
KEEP(*(.exam_mode_buffer))
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = ORIGIN(EXTERNAL_FLASH) + FIRST_EXTERNAL_FLASH_SECTOR_SIZE;
|
||||
_exam_mode_buffer_end = .;
|
||||
} >EXTERNAL_FLASH
|
||||
|
||||
/* External flash memory */
|
||||
.text.external : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} >EXTERNAL_FLASH_NEXT_SECTORS
|
||||
} >EXTERNAL_FLASH
|
||||
|
||||
.rodata.external : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >EXTERNAL_FLASH_NEXT_SECTORS
|
||||
} >EXTERNAL_FLASH
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
@@ -211,7 +212,7 @@ NOCROSSREFS_TO(.rodata.external .isr_vector_table);
|
||||
NOCROSSREFS_TO(.text.external .header);
|
||||
NOCROSSREFS_TO(.rodata.external .header);
|
||||
|
||||
NOCROSSREFS_TO(.exam_mode_persistence .text.internal);
|
||||
NOCROSSREFS_TO(.exam_mode_persistence .rodata.internal);
|
||||
NOCROSSREFS_TO(.exam_mode_persistence .isr_vector_table);
|
||||
NOCROSSREFS_TO(.exam_mode_persistence .header);
|
||||
NOCROSSREFS_TO(.exam_mode_buffer .text.internal);
|
||||
NOCROSSREFS_TO(.exam_mode_buffer .rodata.internal);
|
||||
NOCROSSREFS_TO(.exam_mode_buffer .isr_vector_table);
|
||||
NOCROSSREFS_TO(.exam_mode_buffer .header);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <ion/exam_mode.h>
|
||||
#include <drivers/config/exam_mode.h>
|
||||
#include "flash.h"
|
||||
#include <assert.h>
|
||||
|
||||
@@ -6,10 +7,15 @@ namespace Ion {
|
||||
namespace ExamMode {
|
||||
|
||||
extern "C" {
|
||||
extern char _exam_mode_persistence_start;
|
||||
extern char _exam_mode_persistence_end;
|
||||
extern char _exam_mode_buffer_start;
|
||||
extern char _exam_mode_buffer_end;
|
||||
}
|
||||
|
||||
char ones[Config::ExamModeBufferSize]
|
||||
__attribute__((section(".exam_mode_buffer")))
|
||||
__attribute__((used))
|
||||
= {EXAM_BUFFER_CONTENT};
|
||||
|
||||
/* The exam mode is written in flash so that it is resilient to resets.
|
||||
* We erase the dedicated flash sector (all bits written to 1) and, upon
|
||||
* activating or deactivating the exam mode we write one bit to 0. To determine
|
||||
@@ -22,16 +28,16 @@ extern "C" {
|
||||
* sector. */
|
||||
|
||||
uint32_t * SignificantExamModeAddress() {
|
||||
uint32_t * persitence_start = (uint32_t *)&_exam_mode_persistence_start;
|
||||
uint32_t * persitence_end = (uint32_t *)&_exam_mode_persistence_end;
|
||||
uint32_t * persitence_start = (uint32_t *)&_exam_mode_buffer_start;
|
||||
uint32_t * persitence_end = (uint32_t *)&_exam_mode_buffer_end;
|
||||
while (persitence_start < persitence_end && *persitence_start == 0x0) {
|
||||
// Skip even number of zero bits
|
||||
persitence_start++;
|
||||
}
|
||||
if (persitence_start == persitence_end) {
|
||||
assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start) >= 0);
|
||||
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start));
|
||||
return (uint32_t *)&_exam_mode_persistence_start;
|
||||
assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start) >= 0);
|
||||
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start));
|
||||
return (uint32_t *)&_exam_mode_buffer_start;
|
||||
}
|
||||
return persitence_start;
|
||||
}
|
||||
|
||||
@@ -74,9 +74,15 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t * args) {
|
||||
KDColor backgroundColor = (n_args >= 5) ? ColorForTuple(args[4]) : KDColorWhite;
|
||||
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
|
||||
KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, textColor, backgroundColor);
|
||||
/* drawString function might take some time to execute so we add an extra check
|
||||
* for user interruption (to avoid freezing in an infinite loop calling
|
||||
* 'drawString' for instance). */
|
||||
/* Before and after execution of "modkandinsky_draw_string",
|
||||
* "micropython_port_vm_hook_loop" is called by "mp_execute_bytecode" and will
|
||||
* call "micropython_port_interrupt_if_needed" every 20000 calls.
|
||||
* However, "drawString" function might take some time to execute leading to
|
||||
* drastically decrease the frequency of calls to
|
||||
* "micropython_port_vm_hook_loop" and thus to
|
||||
* "micropython_port_interrupt_if_needed". So we add an extra
|
||||
* check for user interruption here. This way the user can still interrupt an
|
||||
* infinite loop calling 'drawString' for instance. */
|
||||
micropython_port_interrupt_if_needed();
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -91,9 +97,7 @@ mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t * args) {
|
||||
KDColor color = ColorForTuple(args[4]);
|
||||
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
|
||||
KDIonContext::sharedContext()->fillRect(rect, color);
|
||||
/* fillRect function might take some time to execute so we add an extra check
|
||||
* for user interruption (to avoid freezing in an infinite loop calling
|
||||
* 'fillRect' for instance). */
|
||||
// Cf comment on modkandinsky_draw_string
|
||||
micropython_port_interrupt_if_needed();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user