diff --git a/.gitmodules b/.gitmodules index 711750a..cd26963 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/Alliance-Algorithm/hpm_sdk.git [submodule "firmware/c_board/bsp/tinyusb"] path = firmware/c_board/bsp/tinyusb - url = https://github.com/qzhhhi/tinyusb.git + url = https://github.com/Alliance-Algorithm/tinyusb.git [submodule "firmware/c_board/bsp/cmsis-device-f4"] path = firmware/c_board/bsp/cmsis-device-f4 url = https://github.com/STMicroelectronics/cmsis-device-f4.git diff --git a/firmware/c_board/app/src/app.cpp b/firmware/c_board/app/src/app.cpp index db70da1..54c9d7e 100644 --- a/firmware/c_board/app/src/app.cpp +++ b/firmware/c_board/app/src/app.cpp @@ -20,6 +20,7 @@ #include "firmware/c_board/app/src/spi/spi.hpp" #include "firmware/c_board/app/src/timer/timer.hpp" #include "firmware/c_board/app/src/uart/uart.hpp" +#include "firmware/c_board/app/src/usb/dcd_recovery.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" @@ -75,6 +76,10 @@ App::App() { // NOLINTNEXTLINE(readability-convert-member-functions-to-static) [[noreturn]] void App::run() { while (true) { + if (dwc2_recovery_required()) { + while (true) {} + } + tud_task(); gpio::gpio->poll_periodic_input_samples(); diff --git a/firmware/c_board/app/src/usb/dcd_recovery.hpp b/firmware/c_board/app/src/usb/dcd_recovery.hpp new file mode 100644 index 0000000..03b1c30 --- /dev/null +++ b/firmware/c_board/app/src/usb/dcd_recovery.hpp @@ -0,0 +1,4 @@ +#pragma once + +// Defined in bsp/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c. +extern "C" bool dwc2_recovery_required(); diff --git a/firmware/c_board/app/src/watchdog/watchdog.hpp b/firmware/c_board/app/src/watchdog/watchdog.hpp index d56e8c8..05f224a 100644 --- a/firmware/c_board/app/src/watchdog/watchdog.hpp +++ b/firmware/c_board/app/src/watchdog/watchdog.hpp @@ -7,6 +7,10 @@ #include "firmware/c_board/app/src/utility/lazy.hpp" +#ifndef LIBRMCS_WATCHDOG_RELOAD +# define LIBRMCS_WATCHDOG_RELOAD 250U +#endif + namespace librmcs::firmware::watchdog { class Watchdog { @@ -27,7 +31,7 @@ class Watchdog { static void feed() { LL_IWDG_ReloadCounter(IWDG); } private: - static constexpr uint32_t kReloadValue = 250U; + static constexpr uint32_t kReloadValue = LIBRMCS_WATCHDOG_RELOAD; }; inline constinit Watchdog::Lazy watchdog; diff --git a/firmware/c_board/bootloader/CMakeLists.txt b/firmware/c_board/bootloader/CMakeLists.txt index 3862d81..317ee61 100644 --- a/firmware/c_board/bootloader/CMakeLists.txt +++ b/firmware/c_board/bootloader/CMakeLists.txt @@ -42,6 +42,7 @@ target_include_directories(c_board_bootloader PRIVATE ) c_board_apply_target_options(c_board_bootloader "STM32F407XX_BOOTLOADER.ld") +target_compile_definitions(c_board_bootloader PRIVATE LIBRMCS_WATCHDOG_RELOAD=2000) target_link_libraries(c_board_bootloader PRIVATE tinyusb_bootloader ) diff --git a/firmware/c_board/bootloader/src/flash/metadata.hpp b/firmware/c_board/bootloader/src/flash/metadata.hpp index 3185aae..01234b9 100644 --- a/firmware/c_board/bootloader/src/flash/metadata.hpp +++ b/firmware/c_board/bootloader/src/flash/metadata.hpp @@ -4,6 +4,7 @@ #include +#include "firmware/c_board/app/src/watchdog/watchdog.hpp" #include "firmware/c_board/bootloader/src/flash/layout.hpp" #include "firmware/c_board/bootloader/src/flash/unlock_guard.hpp" #include "firmware/c_board/bootloader/src/utility/assert.hpp" @@ -187,6 +188,8 @@ class Metadata { erase.Sector = FLASH_SECTOR_3; erase.NbSectors = 1; + watchdog::Watchdog::feed(); + uint32_t sector_error; { const auto guard = UnlockGuard(); diff --git a/firmware/c_board/bootloader/src/flash/writer.hpp b/firmware/c_board/bootloader/src/flash/writer.hpp index d1567a7..d4fb0cf 100644 --- a/firmware/c_board/bootloader/src/flash/writer.hpp +++ b/firmware/c_board/bootloader/src/flash/writer.hpp @@ -9,6 +9,7 @@ #include +#include "firmware/c_board/app/src/watchdog/watchdog.hpp" #include "firmware/c_board/bootloader/include/tusb_config.h" #include "firmware/c_board/bootloader/src/flash/layout.hpp" #include "firmware/c_board/bootloader/src/flash/unlock_guard.hpp" @@ -144,6 +145,8 @@ class Writer { erase.Sector = kAppSectors[index].sector; erase.NbSectors = 1; + watchdog::Watchdog::feed(); + uint32_t sector_error = 0U; utility::assert_always(HAL_FLASHEx_Erase(&erase, §or_error) == HAL_OK); } diff --git a/firmware/c_board/bootloader/src/main.cpp b/firmware/c_board/bootloader/src/main.cpp index c2beeaf..0401282 100644 --- a/firmware/c_board/bootloader/src/main.cpp +++ b/firmware/c_board/bootloader/src/main.cpp @@ -7,6 +7,8 @@ #include #include +#include "firmware/c_board/app/src/usb/dcd_recovery.hpp" +#include "firmware/c_board/app/src/watchdog/watchdog.hpp" #include "firmware/c_board/bootloader/src/flash/layout.hpp" #include "firmware/c_board/bootloader/src/flash/validation.hpp" #include "firmware/c_board/bootloader/src/usb/dfu.hpp" @@ -54,10 +56,17 @@ int main() { utility::jump_to_app(flash::kAppStartAddress); } + watchdog::watchdog.init(); + utility::assert_always(tusb_rhport_init(0, nullptr)); while (true) { + if (dwc2_recovery_required()) { + while (true) {} + } + tud_task(); usb::Dfu::instance().poll(); + watchdog::watchdog->feed(); } } diff --git a/firmware/c_board/bootloader/src/utility/assert.cpp b/firmware/c_board/bootloader/src/utility/assert.cpp new file mode 100644 index 0000000..0e6f0de --- /dev/null +++ b/firmware/c_board/bootloader/src/utility/assert.cpp @@ -0,0 +1,23 @@ +#include "core/src/utility/assert.hpp" + +#include + +#include // IWYU pragma: keep (disable irq) + +namespace librmcs::core::utility { + +const char* volatile assert_file = nullptr; +volatile unsigned int assert_line = 0; +const char* volatile assert_function = nullptr; + +[[noreturn]] void assert_func(const std::source_location& location) { + __disable_irq(); + + assert_file = location.file_name(); + assert_line = location.line(); + assert_function = location.function_name(); + + __builtin_trap(); +} + +} // namespace librmcs::core::utility diff --git a/firmware/c_board/bsp/tinyusb b/firmware/c_board/bsp/tinyusb index bb24b0c..1291ead 160000 --- a/firmware/c_board/bsp/tinyusb +++ b/firmware/c_board/bsp/tinyusb @@ -1 +1 @@ -Subproject commit bb24b0cada3606af54a0545ac6c48bf673669381 +Subproject commit 1291ead105d43fb74eef6b055c309bb8d6df9124 diff --git a/firmware/rmcs_board/app/src/app.cpp b/firmware/rmcs_board/app/src/app.cpp index ccd5e97..19aa6cf 100644 --- a/firmware/rmcs_board/app/src/app.cpp +++ b/firmware/rmcs_board/app/src/app.cpp @@ -12,6 +12,7 @@ #include "firmware/rmcs_board/app/src/spi/bmi088/temperature.hpp" #include "firmware/rmcs_board/app/src/timer/timer.hpp" #include "firmware/rmcs_board/app/src/uart/uart.hpp" +#include "firmware/rmcs_board/app/src/usb/dcd_recovery.hpp" #include "firmware/rmcs_board/app/src/usb/vendor.hpp" #include "firmware/rmcs_board/app/src/utility/boot_mailbox.hpp" #include "firmware/rmcs_board/app/src/utility/interrupt_lock.hpp" @@ -54,6 +55,10 @@ App::App() { // NOLINTNEXTLINE(readability-convert-member-functions-to-static) [[noreturn]] void App::run() { while (true) { + if (usb_device_recovery_required()) { + while (true) {} + } + tud_task(); usb::vendor->try_transmit(); diff --git a/firmware/rmcs_board/app/src/usb/dcd_recovery.hpp b/firmware/rmcs_board/app/src/usb/dcd_recovery.hpp new file mode 100644 index 0000000..3b8d676 --- /dev/null +++ b/firmware/rmcs_board/app/src/usb/dcd_recovery.hpp @@ -0,0 +1,4 @@ +#pragma once + +// Defined in bsp/hpm_sdk/components/usb/device/hpm_usb_device.c. +extern "C" bool usb_device_recovery_required(); diff --git a/firmware/rmcs_board/app/src/watchdog/watchdog.hpp b/firmware/rmcs_board/app/src/watchdog/watchdog.hpp index 08ebaae..c504709 100644 --- a/firmware/rmcs_board/app/src/watchdog/watchdog.hpp +++ b/firmware/rmcs_board/app/src/watchdog/watchdog.hpp @@ -3,12 +3,17 @@ #include #include +#include #include #include #include "core/src/utility/assert.hpp" #include "firmware/rmcs_board/app/src/utility/lazy.hpp" +#ifndef LIBRMCS_WATCHDOG_TIMEOUT_US +# define LIBRMCS_WATCHDOG_TIMEOUT_US (500'000U) +#endif + namespace librmcs::firmware::watchdog { class Watchdog { @@ -35,7 +40,7 @@ class Watchdog { static void feed() { core::utility::assert_always(ewdg_refresh(HPM_EWDG0) == status_success); } private: - static constexpr uint32_t kTimeoutUs = 500'000U; + static constexpr uint32_t kTimeoutUs = LIBRMCS_WATCHDOG_TIMEOUT_US; static constexpr uint32_t kClockFrequencyHz = 32'768U; }; diff --git a/firmware/rmcs_board/bootloader/CMakeLists.txt b/firmware/rmcs_board/bootloader/CMakeLists.txt index 74d25e1..d3ccf6f 100644 --- a/firmware/rmcs_board/bootloader/CMakeLists.txt +++ b/firmware/rmcs_board/bootloader/CMakeLists.txt @@ -63,6 +63,7 @@ endif() sdk_compile_definitions(-DLIBRMCS_PROJECT_VERSION_STRING="${LIBRMCS_PROJECT_VERSION}") sdk_compile_definitions(-DLIBRMCS_DEBUG_ASSERTS=${LIBRMCS_DEBUG_ASSERTS}) +sdk_compile_definitions(-DLIBRMCS_WATCHDOG_TIMEOUT_US=1000000) sdk_compile_definitions(-DCFG_TUSB_MCU=OPT_MCU_HPM) sdk_compile_definitions(-DUSB_HOST_MCU_CORE=HPM_CORE0) sdk_compile_definitions(-DLIBRMCS_BOOTLOADER_MODE_AUTO=${bootloader_mode_auto}) diff --git a/firmware/rmcs_board/bootloader/src/flash/xpi_nor.hpp b/firmware/rmcs_board/bootloader/src/flash/xpi_nor.hpp index 32c537d..12a05b6 100644 --- a/firmware/rmcs_board/bootloader/src/flash/xpi_nor.hpp +++ b/firmware/rmcs_board/bootloader/src/flash/xpi_nor.hpp @@ -14,6 +14,7 @@ #include #include +#include "firmware/rmcs_board/app/src/watchdog/watchdog.hpp" #include "firmware/rmcs_board/bootloader/src/flash/layout.hpp" #include "firmware/rmcs_board/bootloader/src/utility/assert.hpp" @@ -31,6 +32,8 @@ class XpiNor { void erase_sector(uintptr_t address) { utility::assert_debug((address % sector_size_) == 0U); + watchdog::Watchdog::feed(); + const uint32_t irq_flags = disable_global_irq(CSR_MSTATUS_MIE_MASK); const hpm_stat_t status = rom_xpi_nor_erase_sector( BOARD_APP_XPI_NOR_XPI_BASE, xpi_xfer_channel_auto, &nor_config_, diff --git a/firmware/rmcs_board/bootloader/src/main.cpp b/firmware/rmcs_board/bootloader/src/main.cpp index 5f7515b..27b3d33 100644 --- a/firmware/rmcs_board/bootloader/src/main.cpp +++ b/firmware/rmcs_board/bootloader/src/main.cpp @@ -3,6 +3,8 @@ #include #include +#include "firmware/rmcs_board/app/src/usb/dcd_recovery.hpp" +#include "firmware/rmcs_board/app/src/watchdog/watchdog.hpp" #include "firmware/rmcs_board/bootloader/src/flash/validation.hpp" #include "firmware/rmcs_board/bootloader/src/usb/dfu.hpp" #include "firmware/rmcs_board/bootloader/src/usb/usb_descriptors.hpp" @@ -27,6 +29,9 @@ int main() { // Reset-time clocks already run CPU0 at 360 MHz, so board_init() would only bump it to // 480 MHz while adding avoidable startup latency on the direct-to-app path. board_init(); + + watchdog::watchdog.init(); + board_init_usb(); (void)usb::get_usb_descriptors(); @@ -37,7 +42,12 @@ int main() { utility::assert_always(tusb_rhport_init(0, &init_config)); while (true) { + if (usb_device_recovery_required()) { + while (true) {} + } + tud_task(); usb::Dfu::instance().poll(); + watchdog::watchdog->feed(); } } diff --git a/firmware/rmcs_board/bootloader/src/utility/assert.cpp b/firmware/rmcs_board/bootloader/src/utility/assert.cpp new file mode 100644 index 0000000..eb39007 --- /dev/null +++ b/firmware/rmcs_board/bootloader/src/utility/assert.cpp @@ -0,0 +1,24 @@ +#include "core/src/utility/assert.hpp" + +#include + +#include +#include + +namespace librmcs::core::utility { + +const char* volatile assert_file = nullptr; +volatile unsigned int assert_line = 0; +const char* volatile assert_function = nullptr; + +[[noreturn]] void assert_func(const std::source_location& location) { + disable_global_irq(CSR_MSTATUS_MIE_MASK); + + assert_file = location.file_name(); + assert_line = location.line(); + assert_function = location.function_name(); + + __builtin_trap(); +} + +} // namespace librmcs::core::utility diff --git a/firmware/rmcs_board/bsp/hpm_sdk b/firmware/rmcs_board/bsp/hpm_sdk index a82a535..97168c2 160000 --- a/firmware/rmcs_board/bsp/hpm_sdk +++ b/firmware/rmcs_board/bsp/hpm_sdk @@ -1 +1 @@ -Subproject commit a82a53544d5679a43b70f390c8bbbb8e91f6b8c1 +Subproject commit 97168c2d52ce9997fa9af7a5cd37f7f8cd90befb