From 7a2b432bfaa5409685dfd2c65f2c4b60e102b7bd Mon Sep 17 00:00:00 2001 From: Totoo Date: Thu, 22 Jan 2026 15:24:42 +0100 Subject: [PATCH] Dyn flash size (#2933) --- .gitignore | 1 + CMakeLists.txt | 21 +++++++ firmware/CMakeLists.txt | 2 +- firmware/application/CMakeLists.txt | 3 + .../application/apps/ui_flash_utility.cpp | 9 ++- .../application/apps/ui_flash_utility.hpp | 4 +- firmware/application/ui_navigation.cpp | 2 +- firmware/application/usb_serial_shell.cpp | 21 +++++++ firmware/baseband/proc_flash_utility.cpp | 4 +- .../GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld | 2 +- firmware/common/memory_map.hpp | 3 +- firmware/flashsize.h | 9 +++ firmware/tools/docker-entrypoint.sh | 55 +++++++++++++++---- firmware/tools/make_spi_image.py | 8 +-- flashsize.h.in | 9 +++ hackrf | 2 +- 16 files changed, 130 insertions(+), 25 deletions(-) create mode 100644 firmware/flashsize.h create mode 100644 flashsize.h.in diff --git a/.gitignore b/.gitignore index dae8329db..7136b0ee3 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ venv/ # generated bitmap arr file # TODO: generate bitmap during build, since we use python during build anyway, lemme know if this is a bad idea @zxkmm /firmware/tools/bitmap.hpp +firmware/flashsize.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fbd8a82f..01dd89426 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,27 @@ set(CMAKE_COLOR_MAKEFILE ON) add_compile_options(-fdiagnostics-color=always) +#Flash size related options +#This is the size of the flash memory we SUPPORT. Don't worry, the internl flash app has harder limits based on device type. +if(NOT DEFINED FLASH_MB_SIZE) + set(FLASH_MB_SIZE 2) # Default to 2MB if not provided. For PortaRf this should be 2MB passed to cmake with -DFLASH_MB_SIZE=2 +endif() +message("Configuring for FLASH_MB_SIZE=${FLASH_MB_SIZE}MB") +#This is the flash memory size we build. This can be less, so the FW size will be less, so can be flashed with older utils. +if(NOT DEFINED FLASH_MB_LIMIT_SIZE) + set(FLASH_MB_LIMIT_SIZE 1) #TODO: should be ${FLASH_MB_SIZE} remove once we got a stable build for all devices we support with bigger than 1 mb flash +endif() +message("Configuring for FLASH_MB_LIMIT_SIZE=${FLASH_MB_LIMIT_SIZE}MB") + +if(FLASH_MB_SIZE LESS FLASH_MB_LIMIT_SIZE) + message(FATAL_ERROR "Error: The supported flash size is lower than the generated flash file. Build halted.") +endif() + +math(EXPR FLASH_BYTES_SIZE "${FLASH_MB_SIZE} * 1024 * 1024") +math(EXPR FLASH_BYTES_LIMIT_SIZE "${FLASH_MB_LIMIT_SIZE} * 1024 * 1024") +#generate h files +configure_file(flashsize.h.in ${CMAKE_CURRENT_SOURCE_DIR}/firmware/flashsize.h) + option(USE_CCACHE "Enable ccache, please keep an eye on this because sometimes it's not quite stable and generated unusable binary" OFF) project(portapack-h1) diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 161be343b..8499a2852 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -56,7 +56,7 @@ add_subdirectory(test) # NOTE: Dependencies break if the .bin files aren't included in DEPENDS. WTF, CMake? add_custom_command( OUTPUT ${FIRMWARE_FILENAME} - COMMAND ${MAKE_SPI_IMAGE} ${application_BINARY_DIR}/application.bin ${baseband_BINARY_DIR}/baseband.img ${FIRMWARE_FILENAME} + COMMAND ${MAKE_SPI_IMAGE} ${application_BINARY_DIR}/application.bin ${baseband_BINARY_DIR}/baseband.img ${FIRMWARE_FILENAME} ${FLASH_BYTES_LIMIT_SIZE} DEPENDS baseband application ${MAKE_SPI_IMAGE} ${baseband_BINARY_DIR}/baseband.img ${application_BINARY_DIR}/application.bin VERBATIM diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 0b355d05a..3eb1b6703 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -467,6 +467,9 @@ add_custom_command( ) add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC}) +target_link_options(${PROJECT_NAME}.elf PRIVATE + "LINKER:--defsym,LD_FLASH_SIZE=${FLASH_BYTES_LIMIT_SIZE}" +) set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT}) add_definitions(${DEFS}) include_directories(. ${INCDIR}) diff --git a/firmware/application/apps/ui_flash_utility.cpp b/firmware/application/apps/ui_flash_utility.cpp index b15bd7bdc..fcaf160f5 100644 --- a/firmware/application/apps/ui_flash_utility.cpp +++ b/firmware/application/apps/ui_flash_utility.cpp @@ -45,10 +45,15 @@ bool valid_firmware_file(std::filesystem::path::string_type path) { // test read of the whole file just to validate checksum (baseband flash code will re-read when flashing) auto result = firmware_file.open(path.c_str()); if (!result.is_valid()) { + uint64_t file_size = firmware_file.size(); + if (portapack::device_type == portapack::DeviceType::DEV_PORTAPACK && file_size > 1 * 1024 * 1024) { + // Portapack firmware files must not be larger than 1MB + return false; + } + // May need to add a check to portarf and portarf pro too. checksum = 0; - for (uint32_t offset = 0; offset < FLASH_ROM_SIZE; offset += sizeof(read_buffer)) { + for (uint64_t offset = 0; offset < FLASH_ROM_SIZE && offset < file_size; offset += sizeof(read_buffer)) { auto readResult = firmware_file.read(&read_buffer, sizeof(read_buffer)); - if ((!readResult) || (readResult.value() != sizeof(read_buffer))) { // File was smaller than 1MB: // If version is such that the file SHOULD have been 1MB, call it a checksum error (otherwise say it's OK). diff --git a/firmware/application/apps/ui_flash_utility.hpp b/firmware/application/apps/ui_flash_utility.hpp index 0d9f8d9fa..bb393e87a 100644 --- a/firmware/application/apps/ui_flash_utility.hpp +++ b/firmware/application/apps/ui_flash_utility.hpp @@ -32,7 +32,9 @@ #include "untar.hpp" #include -#define FLASH_ROM_SIZE 1048576 +#include "../../flashsize.h" + +#define FLASH_ROM_SIZE (FLASH_SIZE_MB * 1024 * 1024) #define FLASH_STARTING_ADDRESS 0x00000000 #define FLASH_EXPECTED_CHECKSUM 0x00000000 #define FLASH_CHECKSUM_ERROR 0xFFFFFFFF diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index b5603dba3..8cc65b5b0 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -607,7 +607,7 @@ bool InformationView::firmware_checksum_error() { // only checking firmware checksum once per boot if (!fw_checksum_checked) { - fw_checksum_error = (simple_checksum(FLASH_STARTING_ADDRESS, FLASH_ROM_SIZE) != FLASH_EXPECTED_CHECKSUM); + fw_checksum_error = (simple_checksum(FLASH_STARTING_ADDRESS, FLASH_SIZE_LIMIT_MB * 1024 * 1024) != FLASH_EXPECTED_CHECKSUM); } return fw_checksum_error; } diff --git a/firmware/application/usb_serial_shell.cpp b/firmware/application/usb_serial_shell.cpp index 8bd65afe1..610b452c7 100644 --- a/firmware/application/usb_serial_shell.cpp +++ b/firmware/application/usb_serial_shell.cpp @@ -1383,6 +1383,25 @@ static void cmd_getres(BaseSequentialStream* chp, int argc, char* argv[]) { chprintf(chp, res.c_str()); } +static void cmd_getflash(BaseSequentialStream* chp, int argc, char* argv[]) { + (void)argc; + (void)argv; + uint8_t allowrun = FLASH_SIZE_MB; + if (portapack::device_type == portapack::DeviceType::DEV_PORTAPACK) { + allowrun = 1; + } + std::string res = "ALLOWEDFW:" + to_string_dec_uint(FLASH_SIZE_MB) + "\r\nALLOWEDRUNTIME:" + to_string_dec_uint(allowrun) + "\r\nCURRENT:" + to_string_dec_uint(FLASH_SIZE_LIMIT_MB) + "\r\nok\r\n"; + chprintf(chp, res.c_str()); +} + +static void cmd_getdevtype(BaseSequentialStream* chp, int argc, char* argv[]) { + (void)argc; + (void)argv; + std::string res = portapack::device_type == portapack::DeviceType::DEV_PORTARF ? "PORTARF" : "PORTAPACK"; + res += "\r\nok\r\n"; + chprintf(chp, res.c_str()); +} + static const ShellCommand commands[] = { {"reboot", cmd_reboot}, {"dfu", cmd_dfu}, @@ -1419,6 +1438,8 @@ static const ShellCommand commands[] = { {"asyncmsg", cmd_asyncmsg}, {"setfreq", cmd_setfreq}, {"getres", cmd_getres}, + {"getflash", cmd_getflash}, + {"getdevtype", cmd_getdevtype}, {NULL, NULL}}; static const ShellConfig shell_cfg1 = { diff --git a/firmware/baseband/proc_flash_utility.cpp b/firmware/baseband/proc_flash_utility.cpp index 32cbd50ca..85a5587f8 100644 --- a/firmware/baseband/proc_flash_utility.cpp +++ b/firmware/baseband/proc_flash_utility.cpp @@ -28,8 +28,10 @@ #include "debug.hpp" #include "portapack_shared_memory.hpp" +#include "../flashsize.h" + #define PAGE_LEN 256U -#define NUM_PAGES 4096U +#define NUM_PAGES (4096U * FLASH_SIZE_MB) void initialize_flash(); void erase_flash(); diff --git a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld index a6a9050e7..b81e61ed0 100755 --- a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld +++ b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld @@ -23,7 +23,7 @@ __process_stack_size__ = 0x1000; /* main() stack */ MEMORY { - flash (rx) : org = 0x00000000, len = 1024k /* SPIFI flash @ 0x140????? */ + flash (rx) : org = 0x00000000, len = LD_FLASH_SIZE /* SPIFI flash @ 0x140????? */ ram (rwx) : org = 0x20000000, len = 64k /* AHB SRAM @ 0x20000000 */ } diff --git a/firmware/common/memory_map.hpp b/firmware/common/memory_map.hpp index afce53694..8a35916be 100644 --- a/firmware/common/memory_map.hpp +++ b/firmware/common/memory_map.hpp @@ -29,6 +29,7 @@ using namespace lpc43xx; #include "utility.hpp" +#include "../flashsize.h" namespace portapack { namespace memory { @@ -70,7 +71,7 @@ constexpr region_t ahb_ram_2{0x2000c000, 16_KiB}; constexpr region_t backup_ram{LPC_BACKUP_REG_BASE, 256}; -constexpr region_t spifi_uncached{LPC_SPIFI_DATA_BASE, 1_MiB}; +constexpr region_t spifi_uncached{LPC_SPIFI_DATA_BASE, FLASH_SIZE_MB * 1024 * 1024}; constexpr region_t spifi_cached{LPC_SPIFI_DATA_CACHED_BASE, spifi_uncached.size()}; ///////////////////////////////// diff --git a/firmware/flashsize.h b/firmware/flashsize.h new file mode 100644 index 000000000..dadfa980d --- /dev/null +++ b/firmware/flashsize.h @@ -0,0 +1,9 @@ +#pragma once +// DO NOT EDIT: IT IS AUTO GENERATED BY CMAKE!!!! + +// clang-format off +//Allowed fw size in MB +#define FLASH_SIZE_MB 2 +//Current compiled fw size in MB +#define FLASH_SIZE_LIMIT_MB 1 +// clang-format on diff --git a/firmware/tools/docker-entrypoint.sh b/firmware/tools/docker-entrypoint.sh index 8c955dd99..63c463db8 100755 --- a/firmware/tools/docker-entrypoint.sh +++ b/firmware/tools/docker-entrypoint.sh @@ -21,35 +21,66 @@ # Boston, MA 02110-1301, USA. # -set -e # exit immediatelly on any failure +set -e # exit immediately on any failure + +# 1. PARSE ARGUMENTS +# We separate arguments into two lists: +# - CMAKE_OPTS: Anything starting with -D (e.g., -DFLASH_MB_SIZE=4) +# - BUILD_ARGS: Everything else (e.g., make, ninja, -j20) + +CMAKE_OPTS=() +BUILD_ARGS=() + +for arg in "$@"; do + if [[ "$arg" == -D* ]]; then + CMAKE_OPTS+=("$arg") + else + BUILD_ARGS+=("$arg") + fi +done + +# Reset the script arguments ($1, $2...) to contain only the BUILD_ARGS. This allows the original logic below to work exactly as before. +set -- "${BUILD_ARGS[@]}" build_make() { cd .. mkdir -p build cd build - cmake .. + cmake "${CMAKE_OPTS[@]}" .. make "$@" - exit 0 # Report success :) + exit 0 } build_ninja() { cd .. mkdir -p build cd build - cmake -G Ninja .. + cmake -G Ninja "${CMAKE_OPTS[@]}" .. ninja "$@" - exit 0 # Report success :) + exit 0 } -if [ "$1" = 'make' ]; then # build the default (or specified) target with make - shift # remove the first item from $@ as we consumed it, we can then pass the rest on to make + +if [ "$1" = 'make' ]; then + # User explicitly typed 'make' + shift build_make "$@" -elif [[ $1 == -j* ]]; then # allow passing -j without typing make_default - # dont shift here as we wanna pass the -j + +elif [[ $1 == -j* ]]; then + # User passed -j20 directly (Implied make) build_make "$@" -elif [ "$1" = 'ninja' ]; then # build the default (or specified) target with ninja - shift # remove the first item from $@ as we consumed it, we can then pass the rest on to make + +elif [ "$1" = 'ninja' ]; then + # User explicitly typed 'ninja' + shift build_ninja "$@" + +elif [ ${#CMAKE_OPTS[@]} -gt 0 ] && [ ${#BUILD_ARGS[@]} -eq 0 ]; then + # User passed ONLY CMake flags (e.g. "-DFLASH_MB_SIZE=4") + # We assume they want to run a default 'make' build. + build_make + fi -exec "$@" +# Fallback for other commands (e.g. /bin/bash) +exec "$@" \ No newline at end of file diff --git a/firmware/tools/make_spi_image.py b/firmware/tools/make_spi_image.py index 0e4b28e50..47924b255 100755 --- a/firmware/tools/make_spi_image.py +++ b/firmware/tools/make_spi_image.py @@ -36,8 +36,9 @@ from pathlib import Path usage_message = """ PortaPack SPI flash image generator -Usage: +Usage: Where paths refer to the .bin files for each component project. + spi_size is the total size of the target flash (e.g. 1048576). """ @@ -166,13 +167,14 @@ def get_gcc_version_from_elf_files_in_giving_path_or_filename_s_path(path): #^^^^^^^^gcc version check from elf file^^^^^^^^ -if len(sys.argv) != 4: +if len(sys.argv) != 5: print(usage_message) sys.exit(-1) application_image = read_image(sys.argv[1]) baseband_image = read_image(sys.argv[2]) output_path = sys.argv[3] +spi_size = int(sys.argv[4], 0) print("\ncheck gcc versions from all elf target\n") application_gcc_versions = get_gcc_version_from_elf_files_in_giving_path_or_filename_s_path(sys.argv[1]) @@ -207,8 +209,6 @@ except Exception as e: #^^^^^^^^external app linker script address check worker^^^^^^^^ -spi_size = 1048576 - images = ( { 'name': 'application', diff --git a/flashsize.h.in b/flashsize.h.in new file mode 100644 index 000000000..a35ea111c --- /dev/null +++ b/flashsize.h.in @@ -0,0 +1,9 @@ +#pragma once +// DO NOT EDIT: IT IS AUTO GENERATED BY CMAKE!!!! + +// clang-format off +//Allowed fw size in MB +#define FLASH_SIZE_MB @FLASH_MB_SIZE@ +//Current compiled fw size in MB +#define FLASH_SIZE_LIMIT_MB @FLASH_MB_LIMIT_SIZE@ +// clang-format on \ No newline at end of file diff --git a/hackrf b/hackrf index 714e0dccc..03e503eb0 160000 --- a/hackrf +++ b/hackrf @@ -1 +1 @@ -Subproject commit 714e0dccc0e376020683fefa4e4f43d9b224c81b +Subproject commit 03e503eb0bd8691e5ed63caff8db65f3eedb22cc