Skip to content

Commit

Permalink
Update for Mbed CE. Switch to including image to install directly int…
Browse files Browse the repository at this point in the history
…o the program
  • Loading branch information
multiplemonomials committed Dec 8, 2024
1 parent 4f206b1 commit 57b5dc6
Show file tree
Hide file tree
Showing 16 changed files with 416 additions and 276 deletions.
18 changes: 0 additions & 18 deletions .circleci/config.yml

This file was deleted.

33 changes: 33 additions & 0 deletions .github/workflows/compile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Example GitHub Actions workflow which provides a CI build for your Mbed CE project.

name: Test that this Mbed project compiles

on: push

jobs:
compile:
runs-on: ubuntu-latest
container: ghcr.io/armmbed/mbed-os-env:master-latest

strategy:
matrix:
mbed_target:
# Change the below to match the target(s) you want to compile the project for.
- K64F

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install python3-venv
run: |
apt-get update
apt-get install -y python3-venv
- name: Build project for ${{ matrix.mbed_target }}
run: |
mkdir build && cd build
cmake .. -GNinja -DMBED_TARGET=${{ matrix.mbed_target }}
ninja
45 changes: 41 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
.build
.mbed
projectfiles
*.py*
# Private key file
signing-keys.pem

# CLion build dirs
cmake-build-*/

# User-specific CLion stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.idea/runConfigurations

# Generated CLion files
.idea/**/contentModel.xml

# Sensitive or high-churn CLion files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# VS Code build dir
build/

# VS Code config files
.vscode/

# Python stuff
*.pyc

# Mac stuff
.DS_Store
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "mbed-os"]
path = mbed-os
url = https://github.com/mbed-ce/mbed-os.git
[submodule "mcuboot"]
path = mcuboot
url = https://github.com/multiplemonomials/mcuboot.git
62 changes: 31 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
# Copyright (c) 2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.19)
cmake_policy(VERSION 3.19)

# Mbed-MCUboot Demo Application
set(MBED_APP_JSON_PATH mbed_app.json5)

cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)
include(mbed-os/tools/cmake/app.cmake)

set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mbed-os CACHE INTERNAL "")
set(MCUBOOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot CACHE INTERNAL "")
set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")
set(APP_TARGET application)
# Make sure that the build system generates both bin and hex files, regardless of
# target settings.
set(MBED_OUTPUT_EXT "" CACHE STRING "" FORCE)

include(${MBED_PATH}/tools/cmake/app.cmake)
add_subdirectory(mbed-os)

project(${APP_TARGET})
project(mbed-mcuboot-demo-app)

add_subdirectory(${MBED_PATH})
add_subdirectory(${MCUBOOT_PATH}/boot/bootutil/)
add_subdirectory(${MCUBOOT_PATH}/boot/mbed/) # Mbed-MCUboot Port
# Compile mcuboot sources
add_subdirectory(mcuboot/boot/bootutil)
add_subdirectory(mcuboot/boot/mbed)

add_executable(${APP_TARGET})
add_executable(SimpleApp SimpleApp.cpp secondary_bd.cpp)
target_link_libraries(SimpleApp
mbed-baremetal
mbed-storage
mbed-mcuboot)
mbed_set_post_build(SimpleApp)

target_sources(${APP_TARGET}
PUBLIC
main.cpp
)
add_executable(UpdaterApp UpdaterApp.cpp secondary_bd.cpp)
target_link_libraries(UpdaterApp
mbed-os
mbed-storage
mbed-mcuboot)
mbed_set_post_build(UpdaterApp)

target_link_libraries(${APP_TARGET}
PUBLIC
bootutil
mbed-mcuboot
mbed-storage
mbed-os
)
# Time for a bit of CMake magic: we take the bin file for SimpleApp, then link it into
# UpdaterApp as block of constant data. The name in code is based on the filename passed
# here to the linker.
# See here for more details on this: https://gareus.org/wiki/embedding_resources_in_executables
target_link_options(UpdaterApp PRIVATE -Wl,-b,binary,$<TARGET_FILE_BASE_NAME:SimpleApp>.bin -Wl,-b,elf32-littlearm)
add_dependencies(UpdaterApp SimpleApp) # Ensure SimpleApp gets built before UpdaterApp

mbed_set_post_build(${APP_TARGET})

option(VERBOSE_BUILD "Have a verbose build process")
if(VERBOSE_BUILD)
set(CMAKE_VERBOSE_MAKEFILE ON)
endif()
mbed_finalize_build()
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This example project shows how to configure an Mbed-OS application to be booted by an mcuboot bootloader.

All information for this example has been moved to the combined README in the bootloader repository, [`mbed-mcuboot-demo`](https://github.com/AGlass0fMilk/mbed-mcuboot-demo).
All information for this example has been moved to the combined README in the bootloader repository, [`mbed-mcuboot-bootloader`](https://github.com/mbed-ce/mbed-mcuboot-bootloader).

### License and contributions

Expand Down
90 changes: 90 additions & 0 deletions SimpleApp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2024 Jamie Smith
* SPDX-License-Identifier: Apache-2.0
*
* The Simple App is an application which simply has the ability to set the
* update complete flag, and otherwise just blinks the LED and prints messages.
*/

#include "mbed.h"
#include "mbed-trace/mbed_trace.h"

#include "bootutil/bootutil.h"

#define TRACE_GROUP "SimpleApp"

#if DEMO_BUTTON_ACTIVE_LOW
#define DEMO_BUTTON_IS_PRESSED !btn
#else
#define DEMO_BUTTON_IS_PRESSED btn
#endif

int main()
{
// Enable traces from relevant trace groups
mbed_trace_init();
mbed_trace_include_filters_set("SimpleApp,MCUb,BL");

DigitalIn btn(DEMO_BUTTON);
DigitalOut led(LED1);

// Check if an update has been performed
int swap_type = boot_swap_type();
int ret;
switch (swap_type)
{
case BOOT_SWAP_TYPE_NONE:
tr_info("Regular boot");
break;

case BOOT_SWAP_TYPE_REVERT:
// After MCUboot has swapped a (non-permanent) update image
// into the primary slot, it defaults to reverting the image on the NEXT boot.
// This is why we see "[INFO][MCUb]: Swap type: revert" which can be misleading.
// Confirming the CURRENT boot dismisses the reverting.
tr_info("Firmware update applied successfully");

// Do whatever is needed to verify the firmware is okay (eg: self test)
// then mark the update as successful. Here we let the user press a button.
tr_info("Press the button to confirm, or reboot to revert the update");

while (DEMO_BUTTON_IS_PRESSED)
{
ThisThread::sleep_for(10ms);
}

ret = boot_set_confirmed();
if (ret == 0)
{
tr_info("Current firmware set as confirmed");
return 0;
}
else
{
tr_error("Failed to confirm the firmware: %d", ret);
}
break;

// Note: Below are intermediate states of MCUboot and
// should never reach the application...
case BOOT_SWAP_TYPE_FAIL: // Unable to boot due to invalid image
case BOOT_SWAP_TYPE_PERM: // Permanent update requested (when signing the image) and to be performed
case BOOT_SWAP_TYPE_TEST: // Revertable update requested and to be performed
case BOOT_SWAP_TYPE_PANIC: // Unrecoverable error
default:
tr_error("Unexpected swap type: %d", swap_type);
}

while(true)
{
ThisThread::sleep_for(1s);
printf("Simple app is running...\n");
led = 1;
ThisThread::sleep_for(250ms);
led = 0;
ThisThread::sleep_for(250ms);
led = 1;
ThisThread::sleep_for(250ms);
led = 0;
}
}
91 changes: 91 additions & 0 deletions UpdaterApp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2020 Embedded Planet
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/

#include "mbed.h"

#include "bootutil/bootutil.h"
#include "bootutil/image.h"
#include "flash_map_backend/secondary_bd.h"

#include "FlashIAP/FlashIAPBlockDevice.h"
#include "blockdevice/BufferedBlockDevice.h"
#include "drivers/InterruptIn.h"

#define TRACE_GROUP "UpdaterApp"
#include "mbed-trace/mbed_trace.h"

#if DEMO_BUTTON_ACTIVE_LOW
#define DEMO_BUTTON_IS_PRESSED !btn
#else
#define DEMO_BUTTON_IS_PRESSED btn
#endif

// SimpleApp.bin gets loaded into ram between these addresses.
// See CMakeLists.txt for details on how this is done.
extern "C" uint8_t _binary_SimpleApp_bin_start;
extern "C" uint8_t _binary_SimpleApp_bin_end;
const size_t SimpleApp_bin_length = &_binary_SimpleApp_bin_end - &_binary_SimpleApp_bin_start;

int main()
{
// Enable traces from relevant trace groups
mbed_trace_init();
mbed_trace_include_filters_set("UpdaterApp,MCUb,BL");

DigitalIn btn(DEMO_BUTTON);

// Erase secondary slot
// On the first boot, the secondary BlockDevice needs to be clean
// If the first boot is not normal, please run the erase step, then reboot

tr_info("> Press button to erase secondary slot");

while(!DEMO_BUTTON_IS_PRESSED) {
ThisThread::sleep_for(10ms);
}

BlockDevice *secondary_bd = get_secondary_bd();
int ret = secondary_bd->init();
if (ret == 0) {
tr_info("Secondary BlockDevice inited");
} else {
tr_error("Cannot init secondary BlockDevice: %d", ret);
}

// Use a buffered block device to allow arbitrary length writes to the underlying BD
BufferedBlockDevice bufferedSecBD(secondary_bd);

tr_info("Erasing secondary BlockDevice...");
ret = bufferedSecBD.erase(0, bufferedSecBD.size());
if (ret == 0) {
tr_info("Secondary BlockDevice erased");
} else {
tr_error("Cannot erase secondary BlockDevice: %d", ret);
}

tr_info("> Press button to copy update image to secondary BlockDevice");

while(!DEMO_BUTTON_IS_PRESSED) {
ThisThread::sleep_for(10ms);
}

// Copy the update image from internal flash to secondary BlockDevice
bufferedSecBD.program(&_binary_SimpleApp_bin_start, 0, SimpleApp_bin_length);

// Activate the image in the secondary BlockDevice
tr_info("> Image copied to secondary BlockDevice, press button to activate");

while(!DEMO_BUTTON_IS_PRESSED) {
ThisThread::sleep_for(10ms);
}

ret = boot_set_pending(false);
if (ret == 0) {
tr_info("> Secondary image pending, reboot to update");
} else {
tr_error("Failed to set secondary image pending: %d", ret);
}
}
Loading

0 comments on commit 57b5dc6

Please sign in to comment.