Merge branch 'upsilon-dev' into build-on-arm

This commit is contained in:
Yaya-Cout
2025-11-05 14:29:20 +00:00
committed by GitHub
13 changed files with 163 additions and 71 deletions

View File

@@ -146,49 +146,66 @@ jobs:
submodules: 'recursive'
- run: mkdir final-output
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.en.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.en.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
# We need to duplicate make to work around i18n generator race condition in Makefile leading to inconsistent incremental rebuilds
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.fr.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.fr.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.nl.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.nl.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.pt.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.pt.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.it.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.it.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.de.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.de.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.es.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.es.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.hu.bin
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.hu.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.light.bin
- run: mv output/release/device/n0100/flasher.light.bin final-output/flasher.light.bin
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.verbose.bin
- run: mv output/release/device/n0100/flasher.verbose.bin final-output/flasher.verbose.bin
- run: find final-output/ -type f -exec bash -c "shasum -a 256 -b {} > {}.sha256" \;
- run: tar cvfz binpack-n0100.tgz final-output/*
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-directory'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'final-output/'
destination: 'upsilon-binfiles.appspot.com/dev/n100/'
parent: false
- uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-n0100.tgz
path: binpack-n0100.tgz
- uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r final-output/* binfiles/binaries/dev/n100
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
n0110:
runs-on: ubuntu-24.04-arm
steps:
@@ -204,34 +221,43 @@ jobs:
- run: make -j2 MODEL=n0110 epsilon.onboarding.beta.dfu
- run: make -j2 MODEL=n0110 flasher.light.dfu
- run: make -j2 MODEL=n0110 flasher.verbose.dfu
# We don't need bench as it is used only in factory
# - run: make -j2 bench.ram.dfu
# - run: make -j2 bench.flash.dfu
- run: make -j2 MODEL=n0110 flasher.verbose.bin
- run: make -j2 MODEL=n0110 bench.ram.dfu
# - run: make -j2 MODEL=n0110 bench.flash.dfu
- run: make -j2 MODEL=n0110 binpack
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack-n0110.tgz
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-directory'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/device/n0110/binpack/'
destination: 'upsilon-binfiles.appspot.com/dev/n110/'
parent: false
- run: cp output/release/device/n0110/flasher.verbose.bin output/release/device/n0110/binpack/
- run: cd output/release/device/n0110 && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack/binpack.tgz
- uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-n0110.tgz
path: output/release/device/n0110/binpack-n0110.tgz
- uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/device/n0110/binpack/* binfiles/binaries/dev/n110
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
bootloader:
runs-on: ubuntu-24.04-arm
steps:
- run: |
sudo apt-get update
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: 'recursive'
- run: make -j2 MODEL=n0110 bootloader
@@ -248,22 +274,28 @@ jobs:
- run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/
- run: cd output/release/device/bootloader && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
- run: cd output/release/device/bootloader && tar cvfz binpack-bootloader.tgz binpack/*
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-directory'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/device/bootloader/binpack/'
destination: 'upsilon-binfiles.appspot.com/dev/n110/'
parent: false
- uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-bootloader.tgz
path: output/release/device/bootloader/binpack-bootloader.tgz
- uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/device/bootloader/binpack/* binfiles/binaries/dev/n110
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
windows:
runs-on: windows-latest
defaults:

View File

@@ -19,7 +19,7 @@ void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::setLine(Consol
void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), Palette::CodeBackground);
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::BackgroundApps);
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::CodeBackground);
}
KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const {

View File

@@ -27,7 +27,7 @@
#define SCANCODE_OK ((uint64_t)1 << 4)
#define SCANCODE_Back ((uint64_t)1 << 5)
#define SCANCODE_Home ((uint64_t)1 << 6)
#define SCANCODE_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8))
#define SCANCODE_OnOff (((uint64_t)1 << 7) | ((uint64_t)1 << 8))
#define SCANCODE_Shift ((uint64_t)1 << 12)
#define SCANCODE_Alpha ((uint64_t)1 << 13)
#define SCANCODE_XNT ((uint64_t)1 << 14)

View File

@@ -105,7 +105,7 @@ void Boot::bootSlot(Bootloader::Slot s) {
if (!s.userlandHeader()->isOmega() && !s.userlandHeader()->isUpsilon()) {
// We are trying to boot epsilon, so we check the version and show a warning if needed
const char * version = s.userlandHeader()->version();
const char * min = "24.0.2";
const char * min = "24.4.1";
int versionSum = Utility::versionSum(version, strlen(version));
int minimalVersionTrigger = Utility::versionSum(min, strlen(min));
if (versionSum >= minimalVersionTrigger) {

View File

@@ -69,7 +69,12 @@ void Interface::drawLoading() {
for (uint8_t i = 0; i < strlen(Messages::mainTitle); i++) {
char tmp[2] = {Messages::mainTitle[i], '\0'};
ctx->drawString(tmp, KDPoint(initPos + i * (fontSize.width()), ImageStore::Computer->height() + 25 + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite);
Ion::Timing::msleep(50);
int t = 50;
Ion::Events::Event e = Ion::Events::getEvent(&t);
if (e.isKeyboardEvent()){
return;
}
}
Ion::Timing::msleep(500);
}

View File

@@ -81,7 +81,7 @@ public:
constexpr static const char * aboutMessage4 = "and select the OS";
constexpr static const char * aboutMessage5 = "to boot.";
constexpr static const char * bootloaderVersion = "Version 1.1.0 - RECOVER";
constexpr static const char * bootloaderVersion = "Version 1.1.2 - RECOVER.24.4";
//USB NAMES
constexpr static const char * usbUpsilonBootloader = "NumWorks Calculator";

View File

@@ -6,7 +6,7 @@ DEBUG ?= 0
HOME_DISPLAY_EXTERNALS ?= 1
EPSILON_VERSION ?= 15.5.0
OMEGA_VERSION ?= 2.0.2
UPSILON_VERSION ?= 1.0.1-dev
UPSILON_VERSION ?= 1.1.2
# OMEGA_USERNAME ?= N/A
OMEGA_STATE ?= dev
EPSILON_APPS ?= calculation graph rpn code statistics probability solver atomic sequence regression reader settings external

View File

@@ -5,7 +5,9 @@ APPLE_PLATFORM = macos
APPLE_PLATFORM_MIN_VERSION = 10.10
EPSILON_TELEMETRY ?= 0
ARCHS = x86_64
# Build universal binary for both x86_64 and ARM64 by default
# Can be overridden with ARCHS=arm64 or ARCHS=x86_64 for single architecture builds
ARCHS ?= x86_64 arm64
ifdef ARCH
BUILD_DIR := $(BUILD_DIR)/$(ARCH)

View File

@@ -58,8 +58,10 @@ SECTIONS {
} > FLASH
.recovery_boot : {
. = ORIGIN(FLASH) + USERLAND_OFFSET + 0x80;
. = ALIGN(4);
_recovery_boot_start = .;
KEEP(*(.recovery_boot));
_recovery_boot_end = .;
} >FLASH
.text : {

View File

@@ -24,6 +24,8 @@ namespace Ion {
extern char staticStorageArea[];
}
constexpr void * storageAddress = &(Ion::staticStorageArea);
typedef void (*recoveryStartPointerType)();
constexpr recoveryStartPointerType recoveryStartPointer = &(recovery_start);
class KernelHeader {
public:
@@ -77,16 +79,12 @@ public:
m_osType(OSType),
m_upsilonMagicFooter(UpsilonMagic),
m_upsilonExtraMagicHeader(UpsilonExtraMagic),
// FIXME: Since GCC 13, we can't longer store a pointer to a function in the
// class initialization. I don't know if it's a problem in GCC or our code,
// but it's a bit suspicious as the whole class is blank (0x00) in the
// binary with the data available nowhere else (searching for the username
// returns nothing).
// As a workaround, we fixed the address of recovery_start in flash using
// LD script (ion/src/device/bootloader/bootloader_common.ld).
// This line works on GCC 12
// We need to be careful with the pointer to the recovery entrypoint as GCC
// will simply generate a blank userland header if it wasn't able to
// generate it. This code used to work on GCC 12, but is broken since GCC 13
// probably due to the cast preventing LD to just copy the address:
// m_recoveryAddress((uint32_t)recovery_start + 1),
m_recoveryAddress(0x90010080 + 1),
m_recoveryAddress(recoveryStartPointer),
m_extraVersion(1),
m_upsilonExtraMagicFooter(UpsilonExtraMagic) { }
@@ -146,7 +144,7 @@ private:
uint32_t m_osType;
uint32_t m_upsilonMagicFooter;
uint32_t m_upsilonExtraMagicHeader;
uint32_t m_recoveryAddress;
recoveryStartPointerType m_recoveryAddress;
uint32_t m_extraVersion;
uint32_t m_upsilonExtraMagicFooter;
};

View File

@@ -63,7 +63,7 @@ public:
* switching to DFU mode. It does not apply to the calculator.*/
2048, // wTransferSize: Maximum number of bytes that the device can accept per control-write transaction
0x0100),// bcdDFUVersion
m_interfaceDescriptor(
m_interfaceDescriptor1(
0, // bInterfaceNumber
k_dfuInterfaceAlternateSetting, // bAlternateSetting
0, // bNumEndpoints: Other than endpoint 0
@@ -71,9 +71,20 @@ public:
1, // bInterfaceSubClass: DFU
2, // bInterfaceProtocol: DFU Mode (not DFU Runtime, which would be 1)
4, // iInterface: Index of the Interface string, see m_descriptor
&m_interfaceDescriptor2),
m_interfaceDescriptor2(
0, // bInterfaceNumber
k_dfuInterfaceAlternateSetting + 1, // bAlternateSetting
0, // bNumEndpoints: Other than endpoint 0
0xFE, // bInterfaceClass: DFU (https://www.usb.org/defined-class-codes)
1, // bInterfaceSubClass: DFU
2, // bInterfaceProtocol: DFU Mode (not DFU Runtime, which would be 1)
// TODO: Use real descriptor, not required for now as the descriptor isn't
// used anywhere in DFU firmware, but is only present so NumWorks website work.
4, // iInterface: Index of the Interface string, see m_descriptor
&m_dfuFunctionalDescriptor),
m_configurationDescriptor(
9 + 9 + 9, // wTotalLength: configuration descriptor + interface descriptor + dfu functional descriptor lengths
9 + 9 + 9 + 9, // wTotalLength: configuration descriptor + interface descriptor 1 + interface descriptor 2 + dfu functional descriptor lengths2
1, // bNumInterfaces
k_bConfigurationValue, // bConfigurationValue
0, // iConfiguration: No string descriptor for the configuration
@@ -83,7 +94,7 @@ public:
* Bit 5: Remote Wakeup (allows the device to wake up the host when the host is in suspend)
* Bit 4..0: Reserved, set to 0 */
0x32, // bMaxPower: half of the Maximum Power Consumption
&m_interfaceDescriptor),
&m_interfaceDescriptor1),
m_webUSBPlatformDescriptor(
k_webUSBVendorCode,
k_webUSBLandingPageIndex),
@@ -99,6 +110,9 @@ public:
//m_interfaceStringDescriptor("@SRAM/0x20000000/01*256Ke"),
/* Switch to this descriptor to use dfu-util to write in the SRAM.
* FIXME Should be an alternate Interface. */
// Epsilon 25.6.0 descriptors for example
// @SRAM/0x20000000/01*252Ke
// @Flash/0x90030000/61*064Kg,64*064Kg
m_microsoftOSStringDescriptor(k_microsoftOSVendorCode),
m_workshopURLDescriptor(URLDescriptor::Scheme::HTTPS, "getupsilon.web.app"),
m_extendedCompatIdDescriptor("WINUSB"),
@@ -141,7 +155,8 @@ private:
// Descriptors
DeviceDescriptor m_deviceDescriptor;
DFUFunctionalDescriptor m_dfuFunctionalDescriptor;
InterfaceDescriptor m_interfaceDescriptor;
InterfaceDescriptor m_interfaceDescriptor1;
InterfaceDescriptor m_interfaceDescriptor2;
ConfigurationDescriptor m_configurationDescriptor;
WebUSBPlatformDescriptor m_webUSBPlatformDescriptor;
BOSDescriptor m_bosDescriptor;

View File

@@ -11,13 +11,30 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
dummy/keyboard_callback.cpp \
dummy/window_callback.cpp \
clipboard_helper.cpp \
collect_registers_x86_64.s \
collect_registers.cpp \
haptics.cpp \
journal.cpp \
store_script.cpp \
)
# Include architecture-specific assembly files
# When building for a specific architecture (via ARCH variable)
ifdef ARCH
ifeq ($(ARCH),arm64)
ion_src += ion/src/simulator/shared/collect_registers_arm64.s
else
ion_src += ion/src/simulator/shared/collect_registers_x86_64.s
endif
else
# When building universal binary, include both
ifneq ($(filter arm64,$(ARCHS)),)
ion_src += ion/src/simulator/shared/collect_registers_arm64.s
endif
ifneq ($(filter x86_64,$(ARCHS)),)
ion_src += ion/src/simulator/shared/collect_registers_x86_64.s
endif
endif
ifeq ($(EPSILON_TELEMETRY),1)
ion_src += ion/src/simulator/shared/dummy/telemetry_init.cpp
ion_src += ion/src/shared/telemetry_console.cpp

View File

@@ -0,0 +1,21 @@
.text
.global _collect_registers
_collect_registers:
// Save callee-saved registers to the buffer pointed by x0
// ARM64 callee-saved registers: x19-x28, x29 (fp), x30 (lr), sp
stp x19, x20, [x0, #0]
stp x21, x22, [x0, #16]
stp x23, x24, [x0, #32]
stp x25, x26, [x0, #48]
stp x27, x28, [x0, #64]
stp x29, x30, [x0, #80]
// Save stack pointer
mov x1, sp
str x1, [x0, #96]
// Return current stack pointer
mov x0, sp
ret