Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/release-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ jobs:
uses: actions/upload-artifact@v6
with:
name: librmcs-firmware
path: build/librmcs-firmware*
path: |
build/librmcs-firmware*
build/librmcs-bootloader*
if-no-files-found: error

release:
Expand Down
36 changes: 36 additions & 0 deletions .scripts/append_image_hash
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3

import argparse
import hashlib
import struct
import sys

IMAGE_HASH_MAGIC = 0x48415348 # "HASH"


def main() -> None:
parser = argparse.ArgumentParser(
description="Append ImageHash suffix (magic + SHA-256) to a firmware binary."
)
parser.add_argument("input", help="Input binary file")
parser.add_argument(
"-o",
"--output",
required=True,
help="Output file with ImageHash suffix appended",
)
args = parser.parse_args()

with open(args.input, "rb") as f:
firmware = f.read()

sha256 = hashlib.sha256(firmware).digest()
suffix = struct.pack("<I", IMAGE_HASH_MAGIC) + sha256

with open(args.output, "wb") as f:
f.write(firmware)
f.write(suffix)


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions .scripts/lint-targets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ c_board:
- core/include
- firmware/c_board/app/src
- firmware/c_board/app/include
- firmware/c_board/bootloader/src
- firmware/c_board/bootloader/include
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ RUN apt-get update \
git sudo \
zip unzip xz-utils \
openssh-client \
dfu-util \
# Host toolchain
libc6-dev gcc-14 g++-14 \
pkg-config libusb-1.0-0-dev \
Expand Down
6 changes: 4 additions & 2 deletions Dockerfile.build_firmware
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ RUN --mount=type=bind,target=/src,source=.,readonly \
build_dir="/tmp/build-${board}"; \
cmake --preset release -S "firmware/${board}" -B "${build_dir}"; \
cmake --build "${build_dir}"; \
cp "${build_dir}/app/${board}_app.elf" \
"/output/librmcs-firmware-${board}-${LIBRMCS_PROJECT_VERSION}.elf"; \
cp "${build_dir}/bootloader/${board}_bootloader.elf" \
"/output/librmcs-bootloader-${board}.elf"; \
cp "${build_dir}/app/${board}_app.dfu" \
"/output/librmcs-firmware-${board}-${LIBRMCS_PROJECT_VERSION}.dfu"; \
done

FROM scratch AS output
Expand Down
1 change: 1 addition & 0 deletions firmware/c_board/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ endfunction()


add_subdirectory(app)
add_subdirectory(bootloader)
14 changes: 14 additions & 0 deletions firmware/c_board/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_library(tinyusb_app OBJECT)
target_sources(tinyusb_app PRIVATE
${C_BOARD_APP_TINYUSB_COMMON_SOURCES}
"${C_BOARD_APP_TINYUSB_ROOT}/src/class/vendor/vendor_device.c"
"${C_BOARD_APP_TINYUSB_ROOT}/src/class/dfu/dfu_rt_device.c"
)
target_include_directories(tinyusb_app SYSTEM PUBLIC
"${C_BOARD_APP_TINYUSB_ROOT}/src"
Expand Down Expand Up @@ -51,3 +52,16 @@ target_link_libraries(c_board_app PRIVATE
)

c_board_apply_target_options(c_board_app "STM32F407XX_APP.ld")

add_custom_command(TARGET c_board_app POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary
$<TARGET_FILE:c_board_app>
$<TARGET_FILE_DIR:c_board_app>/c_board_app.bin
COMMAND ${LIBRMCS_PROJECT_ROOT}/.scripts/append_image_hash
-o $<TARGET_FILE_DIR:c_board_app>/c_board_app.dfu
$<TARGET_FILE_DIR:c_board_app>/c_board_app.bin
COMMAND dfu-suffix -v 0xA11C -p 0xD401 -d 0x0100
-a $<TARGET_FILE_DIR:c_board_app>/c_board_app.dfu
> /dev/null
COMMENT "Generating c_board_app.dfu"
)
12 changes: 7 additions & 5 deletions firmware/c_board/app/include/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ extern "C" {
# define CFG_TUD_ENDPOINT0_SIZE 64
#endif

#define CFG_TUD_CDC 0
#define CFG_TUD_MSC 0
#define CFG_TUD_HID 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 1
#define CFG_TUD_CDC 0
#define CFG_TUD_MSC 0
#define CFG_TUD_HID 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 1
#define CFG_TUD_DFU_RUNTIME 1
#define CFG_TUD_DFU 0

#define CFG_TUD_VENDOR_EPSIZE 64

Expand Down
7 changes: 6 additions & 1 deletion firmware/c_board/app/src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
#include "firmware/c_board/app/src/spi/spi.hpp"
#include "firmware/c_board/app/src/uart/uart.hpp"
#include "firmware/c_board/app/src/usb/vendor.hpp"
#include "firmware/c_board/app/src/utility/boot_mailbox.hpp"
#include "firmware/c_board/app/src/utility/interrupt_lock.hpp"

int main() { librmcs::firmware::app.init().run(); }
int main() {
SCB->VTOR = 0x08010000U;
librmcs::firmware::app.init().run();
}

namespace librmcs::firmware {

Expand All @@ -28,6 +32,7 @@ App::App() {

HAL_Init();
SystemClock_Config();
utility::boot_mailbox.clear();

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
Expand Down
19 changes: 15 additions & 4 deletions firmware/c_board/app/src/usb/usb_descriptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string_view>
#include <tuple>

#include <class/dfu/dfu.h>
#include <common/tusb_types.h>
#include <device/usbd.h>
#include <main.h>
Expand Down Expand Up @@ -45,6 +46,7 @@ class UsbDescriptors {
case 1: str = kManufacturerString; break;
case 2: str = kProductString; break;
case 3: str = std::string_view{serial_string_.data(), serial_string_.size() - 1}; break;
case 4: str = kDfuRuntimeString; break;
default: return nullptr;
}

Expand Down Expand Up @@ -141,18 +143,26 @@ class UsbDescriptors {
};

private: // Configuration Descriptor
static constexpr size_t kItfNumTotal = 1;
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
enum InterfaceNumber : uint8_t {
kItfNumVendor = 0,
kItfNumDfuRuntime,
kItfNumTotal,
};

static constexpr size_t kConfigTotalLen =
TUD_CONFIG_DESC_LEN + CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN;
static constexpr size_t kConfigTotalLen = TUD_CONFIG_DESC_LEN
+ CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN
+ CFG_TUD_DFU_RUNTIME * TUD_DFU_RT_DESC_LEN;

static constexpr uint8_t kEpnumVendorDataOut = 0x01;
static constexpr uint8_t kEpnumVendorDataIn = 0x81;

static constexpr uint8_t const kConfigurationDescriptorFs[] = {
TUD_CONFIG_DESCRIPTOR(
1, kItfNumTotal, 0, kConfigTotalLen, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
TUD_VENDOR_DESCRIPTOR(0, 0, kEpnumVendorDataOut, kEpnumVendorDataIn, 64),
TUD_VENDOR_DESCRIPTOR(kItfNumVendor, 0, kEpnumVendorDataOut, kEpnumVendorDataIn, 64),
TUD_DFU_RT_DESCRIPTOR(
kItfNumDfuRuntime, 4, DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_WILL_DETACH, 1000, 1024),
};
static_assert(sizeof(kConfigurationDescriptorFs) == kConfigTotalLen);

Expand All @@ -161,6 +171,7 @@ class UsbDescriptors {
static constexpr std::string_view kManufacturerString = "Alliance RoboMaster Team.";
static constexpr std::string_view kProductString =
"RMCS Agent v" LIBRMCS_PROJECT_VERSION_STRING;
static constexpr std::string_view kDfuRuntimeString = "DFU Runtime";
std::array<char, 33> serial_string_{"D4-0000-0000-0000-0000-0000-0000"};

std::array<uint16_t, 128> descriptor_string_buffer_{};
Expand Down
10 changes: 10 additions & 0 deletions firmware/c_board/app/src/usb/vendor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
#include <cstddef>
#include <cstdint>

#include <main.h>

#include "core/src/protocol/serializer.hpp"
#include "firmware/c_board/app/src/usb/helper.hpp"
#include "firmware/c_board/app/src/utility/boot_mailbox.hpp"

namespace librmcs::firmware::usb {

Expand All @@ -21,6 +24,13 @@ void tud_vendor_rx_cb(uint8_t itf, const uint8_t* buffer, uint16_t size) {
{reinterpret_cast<const std::byte*>(buffer), size}, size < Vendor::kMaxPacketSize);
}

void tud_dfu_runtime_reboot_to_dfu_cb() {
utility::boot_mailbox.request_enter_dfu();
__DSB();
__ISB();
NVIC_SystemReset();
}

void tud_suspend_cb(bool remote_wakeup_en) { (void)remote_wakeup_en; }

void tud_resume_cb() {}
Expand Down
29 changes: 29 additions & 0 deletions firmware/c_board/app/src/utility/boot_mailbox.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <cstdint>
#include <type_traits>

namespace librmcs::firmware::utility {

struct BootMailbox {
static constexpr uint32_t kMailboxMagic = 0x524D4353; // "RMCS"
static constexpr uint32_t kMailboxRequestEnterDfu = 0x44465530; // "DFU0"

volatile uint32_t magic;
volatile uint32_t request;

void clear() {
magic = 0;
request = 0;
}

void request_enter_dfu() {
magic = kMailboxMagic;
request = kMailboxRequestEnterDfu;
}
};
inline BootMailbox boot_mailbox __attribute__((section(".boot_mailbox"), aligned(4), used));

static_assert(std::is_standard_layout_v<BootMailbox> && sizeof(BootMailbox) <= 64);

} // namespace librmcs::firmware::utility
47 changes: 47 additions & 0 deletions firmware/c_board/bootloader/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
add_executable(c_board_bootloader)

set(C_BOARD_BOOTLOADER_TINYUSB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../bsp/tinyusb")
cmake_path(ABSOLUTE_PATH C_BOARD_BOOTLOADER_TINYUSB_ROOT NORMALIZE)
set(C_BOARD_BOOTLOADER_TINYUSB_COMMON_SOURCES
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/tusb.c"
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/common/tusb_fifo.c"
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/device/usbd.c"
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/device/usbd_control.c"
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/portable/synopsys/dwc2/dwc2_common.c"
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/portable/synopsys/dwc2/dcd_dwc2.c"
)

add_library(tinyusb_bootloader OBJECT)
target_sources(tinyusb_bootloader PRIVATE
${C_BOARD_BOOTLOADER_TINYUSB_COMMON_SOURCES}
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src/class/dfu/dfu_device.c"
)
target_include_directories(tinyusb_bootloader SYSTEM PUBLIC
"${C_BOARD_BOOTLOADER_TINYUSB_ROOT}/src"
)
target_include_directories(tinyusb_bootloader PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_compile_definitions(tinyusb_bootloader PUBLIC
CFG_TUSB_MCU=OPT_MCU_STM32F4
)
target_link_libraries(tinyusb_bootloader PUBLIC
stm32cubemx
)

file(GLOB_RECURSE C_BOARD_BOOTLOADER_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.c"
)
target_sources(c_board_bootloader PRIVATE
${C_BOARD_BOOTLOADER_SOURCES}
)

target_include_directories(c_board_bootloader PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)

c_board_apply_target_options(c_board_bootloader "STM32F407XX_BOOTLOADER.ld")
target_link_libraries(c_board_bootloader PRIVATE
tinyusb_bootloader
)
45 changes: 45 additions & 0 deletions firmware/c_board/bootloader/include/tusb_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#ifndef CFG_TUSB_MCU
# error CFG_TUSB_MCU must be defined
#endif

#ifndef BOARD_DEVICE_RHPORT_NUM
# define BOARD_DEVICE_RHPORT_NUM 0
#endif

#ifndef BOARD_DEVICE_RHPORT_SPEED
# define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#endif

#if BOARD_DEVICE_RHPORT_NUM == 0
# define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#elif BOARD_DEVICE_RHPORT_NUM == 1
# define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#else
# error "Incorrect RHPort configuration"
#endif

#define CFG_TUSB_OS OPT_OS_NONE

#ifndef CFG_TUD_ENDPOINT0_SIZE
# define CFG_TUD_ENDPOINT0_SIZE 64
#endif

#define CFG_TUD_CDC 0
#define CFG_TUD_MSC 0
#define CFG_TUD_HID 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
#define CFG_TUD_DFU_RUNTIME 0
#define CFG_TUD_DFU 1

#define CFG_TUD_DFU_XFER_BUFSIZE 1024

#ifdef __cplusplus
}
#endif
Loading