mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[bootloader] Run usb stack on Reset+4
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
|
||||
bootloader_src += $(addprefix bootloader/,\
|
||||
main.cpp \
|
||||
slot.cpp \
|
||||
interface.cpp \
|
||||
jump_to_firmware.s \
|
||||
)
|
||||
|
||||
bootloader_src += $(ion_src) $(kandinsky_src) $(liba_src) $(libaxx_src)
|
||||
bootloader_images = $(addprefix bootloader/, \
|
||||
cable.png \
|
||||
computer.png \
|
||||
)
|
||||
|
||||
bootloader_src += $(ion_src) $(kandinsky_src) $(liba_src) $(libaxx_src) $(bootloader_images)
|
||||
|
||||
$(eval $(call depends_on_image,bootloader/interface.cpp,$(bootloader_images)))
|
||||
|
||||
47
bootloader/interface.cpp
Normal file
47
bootloader/interface.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ion.h>
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
#include "computer.h"
|
||||
#include "cable.h"
|
||||
|
||||
namespace Bootloader {
|
||||
|
||||
void Interface::drawImage(KDContext* ctx, const Image* image, int offset) {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
size_t pixelBufferSize;
|
||||
|
||||
if (image != nullptr) {
|
||||
data = image->compressedPixelData();
|
||||
size = image->compressedPixelDataSize();
|
||||
pixelBufferSize = image->width() * image->height();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
KDColor pixelBuffer[4000];
|
||||
assert(pixelBufferSize <= 4000);
|
||||
assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack
|
||||
|
||||
Ion::decompress(
|
||||
data,
|
||||
reinterpret_cast<uint8_t *>(pixelBuffer),
|
||||
size,
|
||||
pixelBufferSize * sizeof(KDColor)
|
||||
);
|
||||
|
||||
KDRect bounds((320 - image->width()) / 2, offset, image->width(), image->height());
|
||||
|
||||
ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr);
|
||||
}
|
||||
|
||||
void Interface::draw() {
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
drawImage(ctx, ImageStore::Computer, 70);
|
||||
drawImage(ctx, ImageStore::Cable, 172);
|
||||
}
|
||||
|
||||
}
|
||||
22
bootloader/interface.h
Normal file
22
bootloader/interface.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef BOOTLOADER_INTERFACE
|
||||
#define BOOTLOADER_INTERFACE
|
||||
|
||||
#include <stdint.h>
|
||||
#include <kandinsky/context.h>
|
||||
#include <escher/image.h>
|
||||
|
||||
namespace Bootloader {
|
||||
|
||||
class Interface {
|
||||
|
||||
private:
|
||||
static void drawImage(KDContext* ctx, const Image* image, int offset);
|
||||
|
||||
public:
|
||||
static void draw();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
11
bootloader/jump_to_firmware.s
Normal file
11
bootloader/jump_to_firmware.s
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
.syntax unified
|
||||
.section .text.jump_to_firmware
|
||||
.align 2
|
||||
.thumb
|
||||
.global jump_to_firmware
|
||||
jump_to_firmware:
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
msr msp, r0
|
||||
bx r1
|
||||
@@ -1,15 +1,32 @@
|
||||
|
||||
#include <ion/backlight.h>
|
||||
#include <ion/display.h>
|
||||
#include <ion/timing.h>
|
||||
#include <ion.h>
|
||||
#include <bootloader/slot.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
void ion_main(int argc, const char * const argv[]) {
|
||||
// Clear the screen
|
||||
Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorBlack);
|
||||
// Initialize the backlight
|
||||
Ion::Backlight::init();
|
||||
while (1) {
|
||||
Ion::Display::pushRectUniform(KDRect(0,0,10,10), KDColorRed);
|
||||
Ion::Timing::msleep(100);
|
||||
Ion::Display::pushRectUniform(KDRect(0,0,10,10), KDColorBlue);
|
||||
Ion::Timing::msleep(100);
|
||||
|
||||
uint64_t scan = Ion::Keyboard::scan();
|
||||
|
||||
if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Four)) {
|
||||
Bootloader::Interface::draw();
|
||||
while (true) {
|
||||
Ion::USB::enable();
|
||||
while (!Ion::USB::isEnumerated()) {
|
||||
}
|
||||
Ion::USB::DFU(false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
ctx->drawString(Bootloader::s_slotA->version(), KDPoint(0, 20));
|
||||
|
||||
*/
|
||||
Bootloader::s_slotA->boot();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
#include <bootloader/slot.h>
|
||||
|
||||
extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
|
||||
|
||||
namespace Bootloader {
|
||||
|
||||
const struct Slot* s_slotA = reinterpret_cast<const struct Slot*>(0x90000000);
|
||||
const struct Slot* s_slotB = reinterpret_cast<const struct Slot*>(0x90400000);
|
||||
|
||||
const Slot* s_slotA = reinterpret_cast<const struct Slot*>(0x90000000);
|
||||
const Slot* s_slotB = reinterpret_cast<const struct Slot*>(0x90400000);
|
||||
|
||||
const char * Slot::version() const {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
const char * Slot::patchLevel() const {
|
||||
return m_patchLevel;
|
||||
}
|
||||
|
||||
const bool Slot::isValid() const {
|
||||
return m_header == Magic && m_footer == Magic;
|
||||
}
|
||||
|
||||
[[ noreturn ]] void Slot::boot() const {
|
||||
jump_to_firmware(m_stackPointer, m_startPointer);
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,21 +5,29 @@
|
||||
|
||||
namespace Bootloader {
|
||||
|
||||
struct Slot {
|
||||
uint32_t unknown;
|
||||
uint32_t signature_offset;
|
||||
uint32_t magik_header;
|
||||
char version[8];
|
||||
char patch_level[8];
|
||||
uint32_t magik_footer;
|
||||
uint32_t* stack_pointer;
|
||||
void(*main_pointer)();
|
||||
class Slot {
|
||||
public:
|
||||
const char * version() const;
|
||||
const char * patchLevel() const;
|
||||
const bool isValid() const;
|
||||
[[ noreturn ]] void boot() const;
|
||||
|
||||
private:
|
||||
Slot();
|
||||
constexpr static uint32_t Magic = 0xDEC00DF0;
|
||||
const uint32_t m_unknown;
|
||||
const uint32_t m_signature;
|
||||
const uint32_t m_header;
|
||||
const char m_version[8];
|
||||
const char m_patchLevel[8];
|
||||
const uint32_t m_footer;
|
||||
const uint32_t* m_stackPointer;
|
||||
const void(*m_startPointer)();
|
||||
};
|
||||
|
||||
extern const struct Slot* s_slotA;
|
||||
extern const struct Slot* s_slotB;
|
||||
extern const Slot* s_slotA;
|
||||
extern const Slot* s_slotB;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@ $(BUILD_DIR)/test.external_flash.read.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_ext
|
||||
$(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_external_flash_write_symbols.o $(call object_for,$(test_external_flash_src) $(test_ion_external_flash_write_src))
|
||||
|
||||
|
||||
$(BUILD_DIR)/bootloader.$(EXE): $(call flavored_object_for,$(bootloader_src))
|
||||
$(BUILD_DIR)/bootloader.$(EXE): $(call flavored_object_for,$(bootloader_src),usbxip)
|
||||
$(BUILD_DIR)/bootloader.$(EXE): LDSCRIPT = ion/test/device/n0110/external_flash_tests.ld
|
||||
|
||||
.PHONY: %_flash
|
||||
|
||||
@@ -40,5 +40,8 @@
|
||||
"apps/probability/images/normal_icon.png" : "probability/normal_icon.png",
|
||||
"apps/probability/images/poisson_icon.png" : "probability/poisson_icon.png",
|
||||
"apps/probability/images/student_icon.png" : "probability/student_icon.png",
|
||||
"apps/probability/images/uniform_icon.png" : "probability/uniform_icon.png"
|
||||
"apps/probability/images/uniform_icon.png" : "probability/uniform_icon.png",
|
||||
|
||||
"bootloader/cable.png": "bootloader/cable.png",
|
||||
"bootloader/computer.png": "bootloader/computer.png"
|
||||
}
|
||||
|
||||
BIN
themes/themes/local/omega_light/bootloader/cable.png
Normal file
BIN
themes/themes/local/omega_light/bootloader/cable.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
BIN
themes/themes/local/omega_light/bootloader/computer.png
Normal file
BIN
themes/themes/local/omega_light/bootloader/computer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user