diff --git a/.gitignore b/.gitignore index 35c3901a..6b0bb4b5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,10 @@ lib/zephyr-workspace/* *.gcov build settings.ini +bootable.uf2 **/__pycache__/ **/*.egg-info/ -bin/ +/bin/ _codeql_detected_source_root diff --git a/.gitmodules b/.gitmodules index ef179827..84800847 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/fprime-zephyr"] path = lib/fprime-zephyr url = https://github.com/fprime-community/fprime-zephyr.git +[submodule "lib/fprime-extras"] + path = lib/fprime-extras + url = https://github.com/LeStarch/fprime-extras diff --git a/.west/config b/.west/config new file mode 100644 index 00000000..8d67d99f --- /dev/null +++ b/.west/config @@ -0,0 +1,6 @@ +[manifest] +path = . +file = west.yml + +[zephyr] +base = ./lib/zephyr-workspace/zephyr diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index b899a717..9cac22bc 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -6,6 +6,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ComDelay/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Drv/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FatalHandler") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FlashWorker/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FsSpace/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ImuManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LoadSwitch/") diff --git a/FprimeZephyrReference/Components/FatalHandler/FatalHandler.cpp b/FprimeZephyrReference/Components/FatalHandler/FatalHandler.cpp index ff0ad029..cea51119 100644 --- a/FprimeZephyrReference/Components/FatalHandler/FatalHandler.cpp +++ b/FprimeZephyrReference/Components/FatalHandler/FatalHandler.cpp @@ -27,23 +27,14 @@ FatalHandler ::FatalHandler(const char* const compName) : FatalHandlerComponentB FatalHandler ::~FatalHandler() {} void FatalHandler::reboot() { -// When running in CI failsafe mode and the board is a teensy, -// then we should invoke bkpt #251 to trigger the soft reboot enabling a -// flash of new software -#if defined(FPRIME_CI_FAILSAFE_CYCLE_COUNT) - // Magic bootloader breakpoint, provided by PRJC - if (strncmp(CONFIG_BOARD, "teensy", 6) == 0) { - asm("bkpt #251"); - } -#endif // Otherwise, use Zephyr to reboot the system sys_reboot(SYS_REBOOT_COLD); } void FatalHandler::FatalReceive_handler(const FwIndexType portNum, FwEventIdType Id) { - Fw::Logger::log("FATAL %" PRI_FwEventIdType "handled.\n", Id); - Os::Task::delay(Fw::TimeInterval(0, 1000)); // Delay to allow log to be processed - this->reboot(); // Reboot the system + Fw::Logger::log("FATAL %" PRI_FwEventIdType " handled.\n", Id); + Os::Task::delay(Fw::TimeInterval(1, 0)); // Delay to allow log to be processed + this->reboot(); // Reboot the system } } // namespace Components diff --git a/FprimeZephyrReference/Components/FlashWorker/CMakeLists.txt b/FprimeZephyrReference/Components/FlashWorker/CMakeLists.txt new file mode 100644 index 00000000..7f9dda2f --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/CMakeLists.txt @@ -0,0 +1,37 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/UpdateStatus/") + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/FlashWorker.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/FlashWorker.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/FlashWorker.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/FlashWorkerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/FlashWorkerTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/FlashWorker/FlashWorker.cpp b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.cpp new file mode 100644 index 00000000..dac22382 --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.cpp @@ -0,0 +1,114 @@ +// ====================================================================== +// \title FlashWorker.cpp +// \author starchmd +// \brief cpp file for FlashWorker component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/FlashWorker/FlashWorker.hpp" + +#include "Os/File.hpp" +#include +#include + +namespace Components { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +FlashWorker ::FlashWorker(const char* const compName) : FlashWorkerComponentBase(compName), m_last_successful(IDLE) {} + +FlashWorker ::~FlashWorker() {} + +// ---------------------------------------------------------------------- +// Flash helpers +// ---------------------------------------------------------------------- + +Update::UpdateStatus FlashWorker ::writeImage(const Fw::StringBase& file_name, Os::File& file) { + const FwSizeType CHUNK = static_cast(sizeof(this->m_data)); + FW_ASSERT(file.isOpen()); + FwSizeType size = 0; + Update::UpdateStatus return_status = Update::UpdateStatus::OP_OK; + int status = flash_img_init_id(&this->m_flash_context, FlashWorker::REGION_NUMBER); + // Read file size, and default to 0 if unavailable + Os::File::Status file_status = file.size(size); + // Loop through file chunk by chunk + for (FwSizeType i = 0; i < size && status == 0 && file_status == Os::File::Status::OP_OK; i += CHUNK) { + FwSizeType read_size = CHUNK; + file_status = file.read(this->m_data, read_size); + if (file_status != Os::File::Status::OP_OK) { + break; + } + status = flash_img_buffered_write(&this->m_flash_context, this->m_data, read_size, true); + if (status != 0) { + break; + } + } + if (file_status != Os::File::Status::OP_OK) { + this->log_WARNING_LO_ImageFileReadError(file_name, Os::FileStatus(static_cast(file_status))); + } + if (status != 0) { + // TODO image op error + } + return return_status; +} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +Update::UpdateStatus FlashWorker ::confirmImage_handler(FwIndexType portNum) { + int status = boot_write_img_confirmed(); + if (status != 0) { + this->log_WARNING_LO_ConfirmImageFailed(static_cast(-1 * status)); + return Update::UpdateStatus::NEXT_BOOT_ERROR; + } + return Update::UpdateStatus::OP_OK; +} + +Update::UpdateStatus FlashWorker ::nextBoot_handler(FwIndexType portNum, const Update::NextBootMode& mode) { + int permanent = (mode == Update::NextBootMode::PERMANENT) ? BOOT_UPGRADE_PERMANENT : BOOT_UPGRADE_TEST; + + int status = boot_request_upgrade(permanent); + if (status != 0) { + this->log_WARNING_LO_NextBootSetFailed(mode, static_cast(-1 * status)); + return Update::UpdateStatus::NEXT_BOOT_ERROR; + } + return Update::UpdateStatus::OP_OK; +} + +void FlashWorker ::prepareImage_handler(FwIndexType portNum) { + Update::UpdateStatus return_status = Update::UpdateStatus::OP_OK; + int status = boot_erase_img_bank(FlashWorker::REGION_NUMBER); + if (status != 0) { + this->log_WARNING_LO_FlashEraseFailed(static_cast(-1 * status)); + return_status = Update::UpdateStatus::PREPARATION_ERROR; + } else { + this->m_last_successful = PREPARE; + } + this->prepareImageDone_out(0, return_status); +} + +void FlashWorker ::updateImage_handler(FwIndexType portNum, const Fw::StringBase& file) { + Os::File image_file; + Update::UpdateStatus return_status = Update::UpdateStatus::OP_OK; + + if (this->m_last_successful != PREPARE) { + return_status = Update::UpdateStatus::UNPREPARED; + this->m_last_successful = IDLE; + this->log_WARNING_LO_NoImagePrepared(); + } else { + Os::File::Status file_status = image_file.open(file.toChar(), Os::File::Mode::OPEN_READ); + if (file_status == Os::File::Status::OP_OK) { + return_status = this->writeImage(file, image_file); + this->m_last_successful = UPDATE; + } else { + return_status = Update::UpdateStatus::IMAGE_FILE_READ_ERROR; + this->m_last_successful = IDLE; + this->log_WARNING_LO_ImageFileReadError(file, static_cast(file_status)); + } + } + this->updateImageDone_out(0, return_status); +} + +} // namespace Components diff --git a/FprimeZephyrReference/Components/FlashWorker/FlashWorker.fpp b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.fpp new file mode 100644 index 00000000..57e0a0be --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.fpp @@ -0,0 +1,34 @@ +module Components { + @ Performs long-running operations for the flash subsystem + active component FlashWorker { + import Update.UpdateWorker + + event NoImagePrepared() severity warning low \ + format "No image has been prepared for update" + + event NextBootSetFailed(mode: Update.NextBootMode, error_number: I32) severity warning low \ + format "Set next boot mode to {} failed (errno: {})" + + event ConfirmImageFailed(error_number: I32) severity warning low \ + format "Confirm image failed (errno: {})" + + event FlashEraseFailed(error_number: I32) severity warning low \ + format "Flash erase failed (errno: {})" + + event ImageFileReadError(file_name: string, error: Os.FileStatus) severity warning low \ + format "Failed to read {} with error {}" + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + } +} diff --git a/FprimeZephyrReference/Components/FlashWorker/FlashWorker.hpp b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.hpp new file mode 100644 index 00000000..6bedd7bf --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/FlashWorker.hpp @@ -0,0 +1,65 @@ +// ====================================================================== +// \title FlashWorker.hpp +// \author starchmd +// \brief hpp file for FlashWorker component implementation class +// ====================================================================== + +#ifndef Update_FlashWorker_HPP +#define Update_FlashWorker_HPP +#include "FprimeZephyrReference/Components/FlashWorker/FlashWorkerComponentAc.hpp" +#include "Os/File.hpp" +#include +namespace Components { + +class FlashWorker final : public FlashWorkerComponentBase { + public: + constexpr static U8 REGION_NUMBER = 1; // slot1 + enum Step { IDLE, PREPARE, UPDATE }; + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct FlashWorker object + FlashWorker(const char* const compName //!< The component name + ); + + //! Destroy FlashWorker object + ~FlashWorker(); + + private: + Update::UpdateStatus writeImage(const Fw::StringBase& file_name, Os::File& image_file); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for confirmImage + //! + //! Confirm that the currently running image is good + Update::UpdateStatus confirmImage_handler(FwIndexType portNum //!< The port number + ) override; + + //! Handler implementation for nextBoot + //! + //! Set the next boot image and mode + Update::UpdateStatus nextBoot_handler(FwIndexType portNum, //!< The port number + const Update::NextBootMode& mode) override; + + //! Handler implementation for prepareImage + void prepareImage_handler(FwIndexType portNum //!< The port number + ) override; + + //! Handler implementation for updateImage + void updateImage_handler(FwIndexType portNum, //!< The port number + const Fw::StringBase& file) override; + + private: + Step m_last_successful; + U8 m_data[CONFIG_IMG_BLOCK_BUF_SIZE]; + struct flash_img_context m_flash_context; +}; + +} // namespace Components + +#endif diff --git a/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/CMakeLists.txt b/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/CMakeLists.txt new file mode 100644 index 00000000..a42d8d56 --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/CMakeLists.txt @@ -0,0 +1,4 @@ +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/UpdateStatus.fpp" +) diff --git a/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/UpdateStatus.fpp b/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/UpdateStatus.fpp new file mode 100644 index 00000000..05e0b668 --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/UpdateStatus/UpdateStatus.fpp @@ -0,0 +1,20 @@ +# UpdateStatus/UpdateStatus.fpp: +# +# File provided by the UpdateWorker component to report status codes back to the Updater component. This is configured +# specifically for the FlashWorker implementation supplied by Proves. +# +# Copyright (c) 2025 Michael Starch +# +# Licensed under the Apache License, Version 2.0. See LICENSE for details. +# +module Update { + @ Status codes used by the Update subsystem. + enum FlashWorkerUpdateStatus { + OP_OK, @< REQUIRED: operation successful + BUSY, @< REQUIRED: operation could not be started because another operation is in-progress + UNPREPARED, @< Preparation step was not completed and not optional + PREPARATION_ERROR, @< An error occurred during the preparation step + IMAGE_FILE_READ_ERROR, @< An error occurred reading the image file + NEXT_BOOT_ERROR @< An error occurred setting the next boot image + } +} diff --git a/FprimeZephyrReference/Components/FlashWorker/docs/sdd.md b/FprimeZephyrReference/Components/FlashWorker/docs/sdd.md new file mode 100644 index 00000000..35f8f861 --- /dev/null +++ b/FprimeZephyrReference/Components/FlashWorker/docs/sdd.md @@ -0,0 +1,66 @@ +# Components::FlashWorker + +Performs long-running operations for the flash subsystem + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 42bae188..a76c1a72 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -50,7 +50,7 @@ module ReferenceDeployment { instance modeManager: Components.ModeManager base id 0x10040000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ - priority 16 + priority 4 # ---------------------------------------------------------------------- # Queued component instances @@ -142,4 +142,7 @@ module ReferenceDeployment { instance startupManager: Components.StartupManager base id 0x1003F000 + instance fileUplinkCollector: Utilities.BufferCollector base id 0x10041000 + + } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 0390534e..6c525002 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -18,6 +18,7 @@ module ReferenceDeployment { import ComCcsds.FramingSubtopology import ComCcsdsUart.Subtopology import FileHandling.Subtopology + import Update.Subtopology # ---------------------------------------------------------------------- # Instances used in the topology @@ -67,9 +68,9 @@ module ReferenceDeployment { instance ina219SysManager instance ina219SolManager instance resetManager + instance fileUplinkCollector instance modeManager - # ---------------------------------------------------------------------- # Pattern graph specifiers # ---------------------------------------------------------------------- @@ -127,6 +128,7 @@ module ReferenceDeployment { lora.comStatusOut -> comDelay.comStatusIn comDelay.comStatusOut ->ComCcsds.framer.comStatusIn + startupManager.runSequence -> cmdSeq.seqRunIn cmdSeq.seqDone -> startupManager.completeSequence } @@ -213,10 +215,17 @@ module ReferenceDeployment { # File Downlink <-> ComQueue FileHandling.fileDownlink.bufferSendOut -> ComCcsdsUart.comQueue.bufferQueueIn[ComCcsds.Ports_ComBufferQueue.FILE] ComCcsdsUart.comQueue.bufferReturnOut[ComCcsds.Ports_ComBufferQueue.FILE] -> FileHandling.fileDownlink.bufferReturn + } + connections FileUplinkCollecting { # Router <-> FileUplink - ComCcsdsUart.fprimeRouter.fileOut -> FileHandling.fileUplink.bufferSendIn - FileHandling.fileUplink.bufferSendOut -> ComCcsdsUart.fprimeRouter.fileBufferReturnIn + fileUplinkCollector.singleOut -> FileHandling.fileUplink.bufferSendIn + FileHandling.fileUplink.bufferSendOut -> fileUplinkCollector.singleIn + + ComCcsdsUart.fprimeRouter.fileOut -> fileUplinkCollector.multiIn[1] + fileUplinkCollector.multiOut[1] -> ComCcsdsUart.fprimeRouter.fileBufferReturnIn + ComCcsds.fprimeRouter.fileOut -> fileUplinkCollector.multiIn[0] + fileUplinkCollector.multiOut[0] -> ComCcsds.fprimeRouter.fileBufferReturnIn } diff --git a/FprimeZephyrReference/project/config/CMakeLists.txt b/FprimeZephyrReference/project/config/CMakeLists.txt index df855eb8..13b518c2 100644 --- a/FprimeZephyrReference/project/config/CMakeLists.txt +++ b/FprimeZephyrReference/project/config/CMakeLists.txt @@ -18,5 +18,7 @@ register_fprime_config( "${CMAKE_CURRENT_LIST_DIR}/LoRaCfg.hpp" "${CMAKE_CURRENT_LIST_DIR}/PlatformCfg.fpp" "${CMAKE_CURRENT_LIST_DIR}/TlmPacketizerCfg.hpp" + "${CMAKE_CURRENT_LIST_DIR}/UpdateConfig.fpp" + "${CMAKE_CURRENT_LIST_DIR}/UpdateStatus.fpp" INTERFACE ) diff --git a/FprimeZephyrReference/project/config/ComCcsdsConfig.fpp b/FprimeZephyrReference/project/config/ComCcsdsConfig.fpp index 9d0bddf8..667d9386 100644 --- a/FprimeZephyrReference/project/config/ComCcsdsConfig.fpp +++ b/FprimeZephyrReference/project/config/ComCcsdsConfig.fpp @@ -35,9 +35,9 @@ module ComCcsdsConfig { module BuffMgr { constant frameAccumulatorSize = 1024 # Must be at least as large as the comm buffer size constant commsBuffSize = 1024 # Size of ring buffer - constant commsFileBuffSize = 1 + constant commsFileBuffSize = 1024 constant commsBuffCount = 5 - constant commsFileBuffCount = 1 + constant commsFileBuffCount = 5 constant commsBuffMgrId = 200 } } diff --git a/FprimeZephyrReference/project/config/UpdateConfig.fpp b/FprimeZephyrReference/project/config/UpdateConfig.fpp new file mode 100644 index 00000000..7c8f924b --- /dev/null +++ b/FprimeZephyrReference/project/config/UpdateConfig.fpp @@ -0,0 +1,32 @@ +# Update/Subtopology/UpdateConfig/UpdateConfig.fpp: +# +# Update Subtopology configuration +# +# Copyright (c) 2025 Michael Starch +# +# Licensed under the Apache License, Version 2.0. See LICENSE for details. +# +module Update { + # Base ID for instance IDs in this subtopology + constant BASE_ID = 0xA0000000 + + module QueueSizes { + constant updater = 5 # Updater should process quickly; small queue + constant worker = 1 # Worker only handles one item at a time + } + + module StackSizes { + constant updater = 4 * 1024 # Minimal stack size, not much processing + constant worker = 4 * 1024 # Minimal stack size, not much processing + } + + module Priorities { + constant updater = 5 # Updater does real-time tasks; higher priority + constant worker = 15 # Worker does slow-running tasks; lower priority + } + + instance worker: Components.FlashWorker base id BASE_ID + 0x1000 \ + queue size QueueSizes.worker \ + stack size StackSizes.worker \ + priority Priorities.worker +} diff --git a/FprimeZephyrReference/project/config/UpdateStatus.fpp b/FprimeZephyrReference/project/config/UpdateStatus.fpp new file mode 100644 index 00000000..99fbcbd9 --- /dev/null +++ b/FprimeZephyrReference/project/config/UpdateStatus.fpp @@ -0,0 +1,11 @@ +# Update/UpdateStatus/UpdateStatus.fpp: +# +# UpdateStatus configuration +# +# Copyright (c) 2025 Michael Starch +# +# Licensed under the Apache License, Version 2.0. See LICENSE for details. +# +module Update { + type UpdateStatus = Update.FlashWorkerUpdateStatus +} diff --git a/Makefile b/Makefile index 1233ce2e..ddad9fb6 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ generate-if-needed: .PHONY: build build: submodules zephyr fprime-venv generate-if-needed ## Build FPrime-Zephyr Proves Core Reference @$(UV_RUN) fprime-util build + ./tools/bin/make-loadable-image ./build-artifacts/zephyr.signed.bin bootable.uf2 .PHONY: test-integration test-integration: uv diff --git a/README.md b/README.md index d70a075e..7d4af25e 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,46 @@ Depending on the comdelay, the gds should turn green every time a packet is sent ## Sequences You can control the specific command lists of the satellite by writing a sequence file. Sequence files are contained in /sequences. For details on how to attack the startup sequence check the sdd in Startup Manager. + +## MCUBootloader + +First, build the bootloader with west. This is easiest accomplished by building the `sysbuild` example "with_mcuboot" in zephyr. + +``` + +in proves-core-reference +cd lib/zephyr-workspace/zephyr/samples/sysbuild/with_mcuboot +/tools/bin/build-with-proves --sysbuild +(example /home/username/proves-core-reference/tools/bin/build-with-proves --sysbuild) +``` + +Once built, cd upload `build/mcuboot/zephyr/zephyr.uf2` like normally done. + +Then build Proves like normal. This will make a UF2, but not for the second flash region. To build a bootable image, use: + +``` +/tools/bin/make-loadable-image ./build-artifacts/zephyr.signed.bin ./bootable.uf2 +``` + +Now upload `bootable.uf2`. This should chain from MCUBoot to the bootable software image, by changing the base address so it appears at slot0. Once you boot into it, you can use the FlashWorker component to write to slot 1 at runtime. + + +Before, you currently need to run + +``` pip install git+http://github.com/LeStarch/fprime-gds.git@0e23d212 ``` (makes UART buffer not overrun but adding sleeps to file upload in gds) + +Now to fileuplink and update other parts. Upload Zephyr.signed.bin using the file uplink file + +set update.updater.update_image_from and set the next boot to book from _____ + +1. prepare image +2. update from (pass in the path) +3. configure_next_boot = test + +(either power cycle or run the reboot command, should reboot and come into that old version of software, check the version telemetry) + +Go to components/flashworker + +regionnumber = 1 try instead region number=2 + +(redo all the stuff) diff --git a/boards/bronco_space/proves_flight_control_board_v5/Kconfig.defconfig b/boards/bronco_space/proves_flight_control_board_v5/Kconfig.defconfig index 53c0c734..c3b08ffe 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/Kconfig.defconfig +++ b/boards/bronco_space/proves_flight_control_board_v5/Kconfig.defconfig @@ -3,10 +3,13 @@ config SOC_RP2350A_M33 default y config USB_SELF_POWERED + bool "Enable USB_SELF_POWERED" default n config USB_CDC_ACM_LOG_LEVEL + int "Log level" default 0 config USB_DEVICE_LOG_LEVEL + int "Log level" default 1 diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 6c2544d3..0d4fdf0e 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -9,8 +9,10 @@ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &qmi; zephyr,console = &cdc_acm_uart0; zephyr,shell-uart = &cdc_acm_uart0; + zephyr,code-partition = &slot0_partition; }; fstab { @@ -56,8 +58,42 @@ zephyr_udc0: &usbd { }; }; +&qmi { + status = "okay"; +}; + &flash0 { - reg = <0x10000000 DT_SIZE_M(4)>; + reg = <0x10000000 DT_SIZE_M(4)>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <0x1>; + #size-cells = <0x1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x100000>; + }; + + slot0_partition: partition@100000 { + label = "current"; + reg = <0x100000 0x100000>; + }; + + slot1_partition: partition@200000 { + label = "golden"; + reg = <0x200000 0x100000>; + }; + + slot2_partition: partition@300000 { + label = "test"; + reg = <0x300000 0x100000>; + }; + + storage_partition: partition@400000 { + label = "storage"; + reg = <0x400000 0xC00000>; + }; + }; }; &timer0 { diff --git a/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig b/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig index 7a5b0c34..278f926c 100644 --- a/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig +++ b/boards/bronco_space/proves_flight_control_board_v5c/proves_flight_control_board_v5c_rp2350a_m33_defconfig @@ -17,8 +17,9 @@ CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=y CONFIG_CDC_ACM_SERIAL_PID=0x000F CONFIG_CDC_ACM_SERIAL_VID=0x0028 CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="PROVES Flight Control Board v5c" - CONFIG_I2C_TCA954X=y +CONFIG_I2C_TCA954X_ROOT_INIT_PRIO=70 +CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO=71 # Sensors CONFIG_LSM6DSO=y diff --git a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33.yaml b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33.yaml index 6880c0c1..2de6ad15 100644 --- a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33.yaml +++ b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33.yaml @@ -2,7 +2,7 @@ identifier: proves_flight_control_board_v5d/rp2350a/m33 name: PROVES Flight Control Board v5d (RP2350, Cortex-M33) type: mcu arch: arm -flash: 4096 +flash: 16384 ram: 520 toolchain: - zephyr diff --git a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig index daaf56bd..7144d9b6 100644 --- a/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig +++ b/boards/bronco_space/proves_flight_control_board_v5d/proves_flight_control_board_v5d_rp2350a_m33_defconfig @@ -19,6 +19,8 @@ CONFIG_CDC_ACM_SERIAL_VID=0x0028 CONFIG_CDC_ACM_SERIAL_PRODUCT_STRING="PROVES Flight Control Board v5d" CONFIG_I2C_TCA954X=y +CONFIG_I2C_TCA954X_ROOT_INIT_PRIO=70 +CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO=71 # Sensors CONFIG_LSM6DSO=y diff --git a/lib/fprime-extras b/lib/fprime-extras new file mode 160000 index 00000000..bb4410af --- /dev/null +++ b/lib/fprime-extras @@ -0,0 +1 @@ +Subproject commit bb4410af69ded5c9f2d5d9c180fdc6f01ced526d diff --git a/prj.conf b/prj.conf index 743d7d1f..fb8012bf 100644 --- a/prj.conf +++ b/prj.conf @@ -69,3 +69,12 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_FS_FATFS_EXFAT=y CONFIG_FS_FATFS_MOUNT_MKFS=y CONFIG_FS_FATFS_FSTAB_AUTOMOUNT=y +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="lib/zephyr-workspace/bootloader/mcuboot/root-rsa-2048.pem" +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUBOOT_BOOTUTIL_LIB=y +CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET=y +CONFIG_MCUBOOT_BOOTLOADER_NO_DOWNGRADE=n diff --git a/requirements.txt b/requirements.txt index ac019235..4037e872 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,5 @@ patool semver tqdm -r lib/fprime/requirements.txt +-r lib/zephyr-workspace/zephyr/scripts/requirements.txt +-r lib/zephyr-workspace/bootloader/mcuboot/zephyr/requirements.txt diff --git a/settings.ini b/settings.ini index 3672f58f..1305a6ba 100644 --- a/settings.ini +++ b/settings.ini @@ -1,7 +1,7 @@ [fprime] project_root: . framework_path: ./lib/fprime -library_locations: ./lib/fprime-zephyr +library_locations: ./lib/fprime-zephyr:./lib/fprime-extras default_toolchain: zephyr default_cmake_options: FPRIME_ENABLE_FRAMEWORK_UTS=OFF diff --git a/tools/bin/build-with-proves b/tools/bin/build-with-proves new file mode 100755 index 00000000..7bad6a60 --- /dev/null +++ b/tools/bin/build-with-proves @@ -0,0 +1,11 @@ +#!/bin/bash +DIRNAME="$(cd "$(dirname $BASH_SOURCE)"; pwd)" +PROVES_ROOT="$(cd ${DIRNAME}/../..; pwd)" + +which west +if (( $? != 0 )) +then + echo "[ERROR] 'west' not found. Source your virtual environment/" + exit 1 +fi +west build -p -b proves_flight_control_board_v5d/rp2350a/m33 "$@" -- -DBOARD_ROOT="${PROVES_ROOT}" diff --git a/tools/bin/make-loadable-image b/tools/bin/make-loadable-image new file mode 100755 index 00000000..8fc230cb --- /dev/null +++ b/tools/bin/make-loadable-image @@ -0,0 +1,12 @@ +#!/bin/bash +DIRNAME="$(cd "$(dirname $BASH_SOURCE)"; pwd)" +ZEPHYR="${ZEPHYR_BASE:-${DIRNAME}/../../lib/zephyr-workspace/zephyr}" + +# Check arguments +if (( $# != 2 )) +then + echo "$0 " + exit 0 +fi + +python3 ${ZEPHYR}/scripts/build/uf2conv.py -c -f 0xe48bff57 -b 0x10100000 -o "$2" "$1" diff --git a/west.yml b/west.yml index 05c4dc99..051b91be 100644 --- a/west.yml +++ b/west.yml @@ -80,6 +80,14 @@ manifest: groups: - crypto + - name: mcuboot + revision: 96576b341ee19f1c3af6622256b0d4f3d408e1e3 + path: lib/zephyr-workspace/bootloader/mcuboot + + - name: fatfs + revision: f4ead3bf4a6dab3a07d7b5f5315795c073db568d + path: lib/zephyr-workspace/modules/fatfs + self: path: . west-commands: west-commands.yml