From e0dcb9c63d709bb011c7019aebf5a63f001af300 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 12:41:57 +0800 Subject: [PATCH 01/14] refactor(gui): move dashboard to top-level gui/ as a consumer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GUI was physically under src/ but §E defines it as a consumer, not core. CMake already isolated it via MICRO_FORGE_GUI=OFF default; this aligns the physical layout with that boundary. gui/CMakeLists.txt now holds the Qt wiring, paralleling examples/test/bench. Core lib + CLI stay zero-dep; default build still 355 green, GUI build produces micro-forge-gui. --- CMakeLists.txt | 16 +++++----------- gui/CMakeLists.txt | 17 +++++++++++++++++ {src/gui => gui}/main.cpp | 0 {src/gui => gui}/main_window.cpp | 0 {src/gui => gui}/main_window.hpp | 0 5 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 gui/CMakeLists.txt rename {src/gui => gui}/main.cpp (100%) rename {src/gui => gui}/main_window.cpp (100%) rename {src/gui => gui}/main_window.hpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e892c5..67f402b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ set(MICRO_FORGE_ARCH_BIT 32 CACHE STRING "Target architecture bit width (32 or 6 set(ARCH_BIT ${MICRO_FORGE_ARCH_BIT}) option(MICRO_FORGE_COVERAGE "Instrument micro_forge with gcov for coverage (COVERAGE-METHODOLOGY §2; build in a dedicated dir, e.g. -B build-cov -DMICRO_FORGE_COVERAGE=ON)" OFF) +option(MICRO_FORGE_GUI "Build the Qt6 dashboard (milestone 04); lives in gui/ and never enters the core library" OFF) add_compile_options(-Wall -Wextra -Werror) @@ -89,16 +90,9 @@ add_subdirectory(examples) add_subdirectory(test) add_subdirectory(bench) -# ── GUI dashboard (milestone 04; see DIRECTIVES §E) ── -# Opt-in: Qt6 is a heavy runtime dep, so the GUI is a separate target that -# defaults OFF and never enters the core `micro_forge` library. The core and -# CLI stay zero-dep; only micro-forge-gui links Qt6::Widgets. Build in a -# dedicated dir, e.g. -B build-gui -DMICRO_FORGE_GUI=ON. -option(MICRO_FORGE_GUI "Build the Qt6 dashboard (milestone 04)" OFF) +# GUI dashboard lives in gui/ as a top-level consumer (milestone 04; DIRECTIVES +# §E). Built only when MICRO_FORGE_GUI=ON — the option is declared above next to +# MICRO_FORGE_COVERAGE. The gui/ subdirectory does all the Qt wiring. if(MICRO_FORGE_GUI) - find_package(Qt6 REQUIRED COMPONENTS Widgets) - set(CMAKE_AUTOMOC ON) - add_executable(micro-forge-gui src/gui/main.cpp src/gui/main_window.cpp) - target_include_directories(micro-forge-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(micro-forge-gui PRIVATE micro_forge Qt6::Widgets) + add_subdirectory(gui) endif() diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt new file mode 100644 index 0000000..a9ba0a3 --- /dev/null +++ b/gui/CMakeLists.txt @@ -0,0 +1,17 @@ +# GUI dashboard — Qt6 Widgets consumer of micro_forge (milestone 04; DIRECTIVES §E). +# +# Entered only when MICRO_FORGE_GUI=ON (guarded in the root CMakeLists). The +# core library stays zero-dep; only this target links Qt6::Widgets. The sim +# runs synchronously in the Qt main thread — never on a QThread (deterministic +# replay). AUTOMOC is needed because MainWindow uses the Q_OBJECT macro. +find_package(Qt6 REQUIRED COMPONENTS Widgets) +set(CMAKE_AUTOMOC ON) + +add_executable(micro-forge-gui + main.cpp + main_window.cpp +) +# main.cpp / main_window.cpp include "gui/main_window.hpp" (header sits next to +# the .cpp here), so the include root is the repo top, not src/. +target_include_directories(micro-forge-gui PRIVATE ${CMAKE_SOURCE_DIR}) +target_link_libraries(micro-forge-gui PRIVATE micro_forge Qt6::Widgets) diff --git a/src/gui/main.cpp b/gui/main.cpp similarity index 100% rename from src/gui/main.cpp rename to gui/main.cpp diff --git a/src/gui/main_window.cpp b/gui/main_window.cpp similarity index 100% rename from src/gui/main_window.cpp rename to gui/main_window.cpp diff --git a/src/gui/main_window.hpp b/gui/main_window.hpp similarity index 100% rename from src/gui/main_window.hpp rename to gui/main_window.hpp From 4a7a7ccd717ce91e349a7bc0d53b0c3668e4a1d2 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 12:51:31 +0800 Subject: [PATCH 02/14] refactor(cli): split introspection (lib) from CLI (consumer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit introspection.{hpp,cpp} was core library code (compiled into micro_forge, the single source of truth consumed by both CLI and GUI per DIRECTIVES §E) but sat under cli/ — a consumer namespace. Moved to its own library module src/introspection/ + include/introspection/, namespace micro_forge::introspection. CLI proper (main/snapshot) moved to top-level cli/, paralleling gui/. CLI is a pure consumer; snapshot.hpp is now an internal header next to its .cpp. The micro-forge binary stays at build/micro-forge so README paths hold. Default build + 355 ctests green; GUI builds; CLI SIGINT smoke flushes a complete JSON snapshot end-to-end. --- CMakeLists.txt | 7 +++++-- {src/cli => cli}/main.cpp | 0 {src/cli => cli}/snapshot.cpp | 6 +++--- {include/cli => cli}/snapshot.hpp | 0 gui/main.cpp | 2 +- gui/main_window.cpp | 4 ++-- gui/main_window.hpp | 2 +- include/arch/arm/cortex_m3/cortex_m3.hpp | 2 +- include/{cli => introspection}/introspection.hpp | 4 ++-- src/{cli => introspection}/introspection.cpp | 6 +++--- test/test_introspection.cpp | 6 +++--- 11 files changed, 21 insertions(+), 18 deletions(-) rename {src/cli => cli}/main.cpp (100%) rename {src/cli => cli}/snapshot.cpp (97%) rename {include/cli => cli}/snapshot.hpp (100%) rename include/{cli => introspection}/introspection.hpp (97%) rename src/{cli => introspection}/introspection.cpp (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67f402b..685f2a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ set(MICRO_FORGE_SOURCES src/tools/memory_dump.cpp src/tools/mmio_trace.cpp src/util/logger.cpp - src/cli/introspection.cpp + src/introspection/introspection.cpp ) add_library(micro_forge STATIC ${MICRO_FORGE_SOURCES}) @@ -82,7 +82,10 @@ if(MICRO_FORGE_COVERAGE) endif() # Unified CLI runner. -add_executable(micro-forge src/cli/main.cpp src/cli/snapshot.cpp) +add_executable(micro-forge cli/main.cpp cli/snapshot.cpp) +# CLI is a top-level consumer (lives in cli/); snapshot.hpp sits next to its +# .cpp there, so the include root is the repo top, not include/ alone. +target_include_directories(micro-forge PRIVATE ${CMAKE_SOURCE_DIR}) target_link_libraries(micro-forge PRIVATE micro_forge) enable_testing() diff --git a/src/cli/main.cpp b/cli/main.cpp similarity index 100% rename from src/cli/main.cpp rename to cli/main.cpp diff --git a/src/cli/snapshot.cpp b/cli/snapshot.cpp similarity index 97% rename from src/cli/snapshot.cpp rename to cli/snapshot.cpp index ff5ed5b..65c774b 100644 --- a/src/cli/snapshot.cpp +++ b/cli/snapshot.cpp @@ -1,12 +1,12 @@ // JSON snapshot serialization. Hand-written, zero external deps. // Addresses/values use lowercase hex strings; numbers stay decimal. // -// Field VALUES come from cli::read_introspection() — the single source of +// Field VALUES come from introspection::read_introspection() — the single source of // truth shared with the GUI dashboard (milestone 04). This file owns only the // JSON text shape; it does no simulator state reading of its own, so CLI and // GUI can never disagree on what a register/fault field holds. #include "cli/snapshot.hpp" -#include "cli/introspection.hpp" +#include "introspection/introspection.hpp" #include "cpu/cpu.hpp" @@ -101,7 +101,7 @@ void json_string(std::ostream& o, std::string_view s) { void write_snapshot_json(chips::stm32f1::Stm32f103Soc& soc, std::ostream& out, const SnapshotExtras& extras) { - const IntrospectionSnapshot snap = read_introspection(soc, extras.usart_output); + const auto snap = introspection::read_introspection(soc, extras.usart_output); out << "{"; // ── cpu ── diff --git a/include/cli/snapshot.hpp b/cli/snapshot.hpp similarity index 100% rename from include/cli/snapshot.hpp rename to cli/snapshot.hpp diff --git a/gui/main.cpp b/gui/main.cpp index 7b55c52..667f0bd 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -1,6 +1,6 @@ // micro-forge GUI dashboard — Qt6 Widgets entry point. // -// Milestone 04: pure consumer of cli::read_introspection(); the simulator +// Milestone 04: pure consumer of introspection::read_introspection(); the simulator // core stays single-threaded and runs in this same Qt main thread (never on // a QThread). See DIRECTIVES §E and notes 031–034. // diff --git a/gui/main_window.cpp b/gui/main_window.cpp index 9fe3aea..de70fb6 100644 --- a/gui/main_window.cpp +++ b/gui/main_window.cpp @@ -1,7 +1,7 @@ // micro-forge GUI main window implementation (G5b/G5c). #include "gui/main_window.hpp" -#include "cli/introspection.hpp" +#include "introspection/introspection.hpp" #include "cpu/cpu.hpp" #include @@ -166,7 +166,7 @@ void MainWindow::refreshFromSnapshot() { if (!soc_) { return; } - const auto snap = cli::read_introspection(*soc_, usart_output_); + const auto snap = introspection::read_introspection(*soc_, usart_output_); const char* st = "?"; switch (snap.cpu.state) { diff --git a/gui/main_window.hpp b/gui/main_window.hpp index 13e9086..9d5b12b 100644 --- a/gui/main_window.hpp +++ b/gui/main_window.hpp @@ -2,7 +2,7 @@ // // Owns the simulator (a Stm32f103Soc) and drives it from the Qt main thread: // a QTimer fires onTick(), which runs a small chunk of steps and refreshes -// the CPU panel from cli::read_introspection(). The sim never runs on a +// the CPU panel from introspection::read_introspection(). The sim never runs on a // QThread — that would break deterministic replay (DIRECTIVES §E). #pragma once diff --git a/include/arch/arm/cortex_m3/cortex_m3.hpp b/include/arch/arm/cortex_m3/cortex_m3.hpp index f9bb157..8748b20 100644 --- a/include/arch/arm/cortex_m3/cortex_m3.hpp +++ b/include/arch/arm/cortex_m3/cortex_m3.hpp @@ -48,7 +48,7 @@ class CortexM3CPU : public CPU { void set_prigroup(uint8_t group) { prigroup_ = group & 0x7u; } bool in_handler_mode() const { return in_handler_mode_; } // Read-only accessors for the status / mask / stack registers. They back - // the structured introspection snapshot (cli::read_introspection) consumed + // the structured introspection snapshot (introspection::read_introspection) consumed // by both the CLI JSON serializer and the GUI dashboard (milestone 04). // Inline by design — an out-of-line copy would still be off the fetch/ // decode hot path, but keeping it header-inline avoids a TU/lookup cost diff --git a/include/cli/introspection.hpp b/include/introspection/introspection.hpp similarity index 97% rename from include/cli/introspection.hpp rename to include/introspection/introspection.hpp index 539a3d2..9ab4290 100644 --- a/include/cli/introspection.hpp +++ b/include/introspection/introspection.hpp @@ -10,7 +10,7 @@ namespace micro_forge::chips::stm32f1 { class Stm32f103Soc; } -namespace micro_forge::cli { +namespace micro_forge::introspection { // Structured introspection snapshot — the single source of truth for the // observable simulator state. Consumed by both the CLI JSON serializer @@ -86,4 +86,4 @@ struct IntrospectionSnapshot { IntrospectionSnapshot read_introspection(chips::stm32f1::Stm32f103Soc& soc, std::string_view usart_output) noexcept; -} // namespace micro_forge::cli +} // namespace micro_forge::introspection diff --git a/src/cli/introspection.cpp b/src/introspection/introspection.cpp similarity index 96% rename from src/cli/introspection.cpp rename to src/introspection/introspection.cpp index 3536bfa..3962f14 100644 --- a/src/cli/introspection.cpp +++ b/src/introspection/introspection.cpp @@ -2,7 +2,7 @@ // Pure read: pulls CPU registers, fault record, run cycles and peripheral // state into plain structs that both the CLI JSON serializer and the GUI // dashboard consume. Owns no serialization format of its own. -#include "cli/introspection.hpp" +#include "introspection/introspection.hpp" #include "arch/arm/cortex_m3/cortex_m3.hpp" #include "chips/stm32f1/stm32f103_soc.hpp" @@ -15,7 +15,7 @@ using namespace micro_forge; using micro_forge::cpu::CPU; using micro_forge::chips::stm32f1::Stm32f103Soc; -namespace micro_forge::cli { +namespace micro_forge::introspection { IntrospectionSnapshot read_introspection(Stm32f103Soc& soc, std::string_view usart_output) noexcept { @@ -85,4 +85,4 @@ IntrospectionSnapshot read_introspection(Stm32f103Soc& soc, return snap; } -} // namespace micro_forge::cli +} // namespace micro_forge::introspection diff --git a/test/test_introspection.cpp b/test/test_introspection.cpp index 04f96b3..d70e30e 100644 --- a/test/test_introspection.cpp +++ b/test/test_introspection.cpp @@ -1,10 +1,10 @@ -// Tests for the structured introspection snapshot (cli::read_introspection). +// Tests for the structured introspection snapshot (introspection::read_introspection). // It is the single source of truth shared by the CLI JSON serializer and the // GUI dashboard (milestone 04). These tests pin: (1) the 7 newly-exposed // status/mask/stack registers are readable; (2) read_introspection is a pure // read — it must not mutate simulator state; (3) on real firmware it observes // the expected advance (state/cycles/pc). -#include "cli/introspection.hpp" +#include "introspection/introspection.hpp" #include "chips/stm32f1/stm32f103_soc.hpp" #include "cpu/cpu.hpp" @@ -17,7 +17,7 @@ #include using namespace micro_forge; -using micro_forge::cli::read_introspection; +using micro_forge::introspection::read_introspection; using micro_forge::chips::stm32f1::Stm32f103Soc; using micro_forge::cpu::CPU; From d7c80b3ddc20f7cda0c1efa3369c7f5468bee173 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 12:55:57 +0800 Subject: [PATCH 03/14] refactor(hdr): unify all headers to .hpp; rename the two def.h Project convention is .hpp (50 files) but 7 legacy headers still used .h. Renamed all 7, and gave the two generic def.h meaningful names matching their contents: arch/arm/cortex_m3/def.h -> cortex_m3_defs.hpp (PSR flags, reg table) loader/utils/def.h -> elf_defs.hpp (ELF magic, Elf32_*) arch/toy/{cpu,isa}.h -> .hpp util/weak_ptr/{weak_ptr,weak_ptr_factory,private/weak_ptr_internals}.h -> .hpp All #include paths updated (including two relative same-dir includes the first sed pass missed: cortex_m3.hpp and weak_ptr_factory.hpp). Zero .h files remain. Default build + 355 ctests + GUI build all green. --- include/arch/arm/cortex_m3/cortex_m3.hpp | 6 +++--- include/arch/arm/cortex_m3/{def.h => cortex_m3_defs.hpp} | 0 include/arch/toy/{cpu.h => cpu.hpp} | 4 ++-- include/arch/toy/{isa.h => isa.hpp} | 0 include/chips/stm32f1/stm32f103_soc.hpp | 2 +- include/chips/stm32f1/stm32f1_afio.hpp | 2 +- include/chips/stm32f1/stm32f1_exti.hpp | 2 +- include/chips/stm32f1/stm32f1_flash.hpp | 2 +- include/chips/stm32f1/stm32f1_gpio.hpp | 2 +- include/chips/stm32f1/stm32f1_rcc.hpp | 2 +- include/chips/stm32f1/stm32f1_timer.hpp | 2 +- include/chips/stm32f1/stm32f1_usart.hpp | 2 +- include/loader/utils/{def.h => elf_defs.hpp} | 0 include/memory/bus.hpp | 2 +- include/memory/flat_memory.hpp | 2 +- include/memory/region.hpp | 2 +- include/periph/nvic.hpp | 2 +- include/periph/scb.hpp | 2 +- include/periph/systick.hpp | 2 +- include/sim/coordinator.hpp | 2 +- .../{weak_ptr_internals.h => weak_ptr_internals.hpp} | 2 +- include/util/weak_ptr/{weak_ptr.h => weak_ptr.hpp} | 2 +- .../weak_ptr/{weak_ptr_factory.h => weak_ptr_factory.hpp} | 4 ++-- src/arch/arm/cortex_m3/cortex_m3.cpp | 2 +- src/arch/toy/cpu.cpp | 2 +- src/loader/elf_loader.cpp | 2 +- src/loader/utils/elf_parser.cpp | 2 +- test/test_coordinator.cpp | 2 +- test/test_cpu.cpp | 4 ++-- 29 files changed, 31 insertions(+), 31 deletions(-) rename include/arch/arm/cortex_m3/{def.h => cortex_m3_defs.hpp} (100%) rename include/arch/toy/{cpu.h => cpu.hpp} (97%) rename include/arch/toy/{isa.h => isa.hpp} (100%) rename include/loader/utils/{def.h => elf_defs.hpp} (100%) rename include/util/weak_ptr/private/{weak_ptr_internals.h => weak_ptr_internals.hpp} (99%) rename include/util/weak_ptr/{weak_ptr.h => weak_ptr.hpp} (99%) rename include/util/weak_ptr/{weak_ptr_factory.h => weak_ptr_factory.hpp} (98%) diff --git a/include/arch/arm/cortex_m3/cortex_m3.hpp b/include/arch/arm/cortex_m3/cortex_m3.hpp index 8748b20..cfa05d7 100644 --- a/include/arch/arm/cortex_m3/cortex_m3.hpp +++ b/include/arch/arm/cortex_m3/cortex_m3.hpp @@ -4,12 +4,12 @@ #include "cpu/cpu.hpp" #include "cpu/fault_record.hpp" #include "cpu/regfile.hpp" -#include "def.h" +#include "cortex_m3_defs.hpp" #include "memory/bus.hpp" #include "periph/nvic.hpp" #include "periph/scb.hpp" -#include "util/weak_ptr/weak_ptr.h" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr.hpp" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include #include diff --git a/include/arch/arm/cortex_m3/def.h b/include/arch/arm/cortex_m3/cortex_m3_defs.hpp similarity index 100% rename from include/arch/arm/cortex_m3/def.h rename to include/arch/arm/cortex_m3/cortex_m3_defs.hpp diff --git a/include/arch/toy/cpu.h b/include/arch/toy/cpu.hpp similarity index 97% rename from include/arch/toy/cpu.h rename to include/arch/toy/cpu.hpp index 7145e6e..77c59af 100644 --- a/include/arch/toy/cpu.h +++ b/include/arch/toy/cpu.hpp @@ -1,11 +1,11 @@ -#include "arch/toy/isa.h" +#include "arch/toy/isa.hpp" #include "autogen/arch_details.hpp" #include "core/types.hpp" #include "cpu/cpu.hpp" #include "cpu/intr.hpp" #include "cpu/regfile.hpp" #include "memory/bus.hpp" -#include "util/weak_ptr/weak_ptr.h" +#include "util/weak_ptr/weak_ptr.hpp" #include #include diff --git a/include/arch/toy/isa.h b/include/arch/toy/isa.hpp similarity index 100% rename from include/arch/toy/isa.h rename to include/arch/toy/isa.hpp diff --git a/include/chips/stm32f1/stm32f103_soc.hpp b/include/chips/stm32f1/stm32f103_soc.hpp index f4f8536..1378fac 100644 --- a/include/chips/stm32f1/stm32f103_soc.hpp +++ b/include/chips/stm32f1/stm32f103_soc.hpp @@ -18,7 +18,7 @@ #include "periph/serial_port.hpp" #include "periph/systick.hpp" #include "periph/timer.hpp" -#include "util/weak_ptr/weak_ptr.h" +#include "util/weak_ptr/weak_ptr.hpp" #include #include diff --git a/include/chips/stm32f1/stm32f1_afio.hpp b/include/chips/stm32f1/stm32f1_afio.hpp index dcb8515..c846cfd 100644 --- a/include/chips/stm32f1/stm32f1_afio.hpp +++ b/include/chips/stm32f1/stm32f1_afio.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include namespace micro_forge::chips::stm32f1 { diff --git a/include/chips/stm32f1/stm32f1_exti.hpp b/include/chips/stm32f1/stm32f1_exti.hpp index 082b392..7829d77 100644 --- a/include/chips/stm32f1/stm32f1_exti.hpp +++ b/include/chips/stm32f1/stm32f1_exti.hpp @@ -3,7 +3,7 @@ #include "cpu/intr.hpp" #include "hooks/events.hpp" #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/chips/stm32f1/stm32f1_flash.hpp b/include/chips/stm32f1/stm32f1_flash.hpp index 74d04f9..e141d0e 100644 --- a/include/chips/stm32f1/stm32f1_flash.hpp +++ b/include/chips/stm32f1/stm32f1_flash.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include namespace micro_forge::chips::stm32f1 { diff --git a/include/chips/stm32f1/stm32f1_gpio.hpp b/include/chips/stm32f1/stm32f1_gpio.hpp index 36c476b..0fcb3eb 100644 --- a/include/chips/stm32f1/stm32f1_gpio.hpp +++ b/include/chips/stm32f1/stm32f1_gpio.hpp @@ -4,7 +4,7 @@ #include "hooks/signal.hpp" #include "periph/device.hpp" #include "periph/gpio.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/chips/stm32f1/stm32f1_rcc.hpp b/include/chips/stm32f1/stm32f1_rcc.hpp index 9e529a3..c65672c 100644 --- a/include/chips/stm32f1/stm32f1_rcc.hpp +++ b/include/chips/stm32f1/stm32f1_rcc.hpp @@ -2,7 +2,7 @@ #include "periph/clock_controller.hpp" #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include diff --git a/include/chips/stm32f1/stm32f1_timer.hpp b/include/chips/stm32f1/stm32f1_timer.hpp index dbe1b9f..421c644 100644 --- a/include/chips/stm32f1/stm32f1_timer.hpp +++ b/include/chips/stm32f1/stm32f1_timer.hpp @@ -2,7 +2,7 @@ #include "periph/device.hpp" #include "periph/timer.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/chips/stm32f1/stm32f1_usart.hpp b/include/chips/stm32f1/stm32f1_usart.hpp index 17b70eb..5a3fb35 100644 --- a/include/chips/stm32f1/stm32f1_usart.hpp +++ b/include/chips/stm32f1/stm32f1_usart.hpp @@ -2,7 +2,7 @@ #include "periph/device.hpp" #include "periph/serial_port.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/loader/utils/def.h b/include/loader/utils/elf_defs.hpp similarity index 100% rename from include/loader/utils/def.h rename to include/loader/utils/elf_defs.hpp diff --git a/include/memory/bus.hpp b/include/memory/bus.hpp index 5463178..67a47e0 100644 --- a/include/memory/bus.hpp +++ b/include/memory/bus.hpp @@ -2,7 +2,7 @@ #include "core/types.hpp" #include "memory/region.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/memory/flat_memory.hpp b/include/memory/flat_memory.hpp index 952eae0..f5b1e0b 100644 --- a/include/memory/flat_memory.hpp +++ b/include/memory/flat_memory.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/memory/region.hpp b/include/memory/region.hpp index b5e7c66..4ed0a4f 100644 --- a/include/memory/region.hpp +++ b/include/memory/region.hpp @@ -2,7 +2,7 @@ #include "autogen/arch_details.hpp" #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr.h" +#include "util/weak_ptr/weak_ptr.hpp" namespace micro_forge::memory { diff --git a/include/periph/nvic.hpp b/include/periph/nvic.hpp index 1ea374a..c5dc0ca 100644 --- a/include/periph/nvic.hpp +++ b/include/periph/nvic.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/periph/scb.hpp b/include/periph/scb.hpp index d288f48..6462e0a 100644 --- a/include/periph/scb.hpp +++ b/include/periph/scb.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/periph/systick.hpp b/include/periph/systick.hpp index 8d51b1b..fc0abeb 100644 --- a/include/periph/systick.hpp +++ b/include/periph/systick.hpp @@ -1,7 +1,7 @@ #pragma once #include "periph/device.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" #include #include diff --git a/include/sim/coordinator.hpp b/include/sim/coordinator.hpp index 9f9c4e0..b041043 100644 --- a/include/sim/coordinator.hpp +++ b/include/sim/coordinator.hpp @@ -3,7 +3,7 @@ #include "cpu/cpu.hpp" #include "periph/device.hpp" #include "sim/virtual_clock.hpp" -#include "util/weak_ptr/weak_ptr.h" +#include "util/weak_ptr/weak_ptr.hpp" #include #include diff --git a/include/util/weak_ptr/private/weak_ptr_internals.h b/include/util/weak_ptr/private/weak_ptr_internals.hpp similarity index 99% rename from include/util/weak_ptr/private/weak_ptr_internals.h rename to include/util/weak_ptr/private/weak_ptr_internals.hpp index 0e1dff3..563a45a 100644 --- a/include/util/weak_ptr/private/weak_ptr_internals.h +++ b/include/util/weak_ptr/private/weak_ptr_internals.hpp @@ -1,5 +1,5 @@ /** - * @file base/include/base/weak_ptr/private/weak_ptr_internals.h + * @file base/include/base/weak_ptr/private/weak_ptr_internals.hpp * @brief Internal implementation details for WeakPtr system. * * This header contains the internal implementation details for the WeakPtr diff --git a/include/util/weak_ptr/weak_ptr.h b/include/util/weak_ptr/weak_ptr.hpp similarity index 99% rename from include/util/weak_ptr/weak_ptr.h rename to include/util/weak_ptr/weak_ptr.hpp index 1ca3c01..fb570f9 100644 --- a/include/util/weak_ptr/weak_ptr.h +++ b/include/util/weak_ptr/weak_ptr.hpp @@ -19,7 +19,7 @@ #include #include -#include "private/weak_ptr_internals.h" +#include "private/weak_ptr_internals.hpp" namespace micro_forge { diff --git a/include/util/weak_ptr/weak_ptr_factory.h b/include/util/weak_ptr/weak_ptr_factory.hpp similarity index 98% rename from include/util/weak_ptr/weak_ptr_factory.h rename to include/util/weak_ptr/weak_ptr_factory.hpp index 83a2b52..2e96fb0 100644 --- a/include/util/weak_ptr/weak_ptr_factory.h +++ b/include/util/weak_ptr/weak_ptr_factory.hpp @@ -18,8 +18,8 @@ #include #include -#include "private/weak_ptr_internals.h" -#include "weak_ptr.h" +#include "private/weak_ptr_internals.hpp" +#include "weak_ptr.hpp" namespace micro_forge { diff --git a/src/arch/arm/cortex_m3/cortex_m3.cpp b/src/arch/arm/cortex_m3/cortex_m3.cpp index bd04642..b146279 100644 --- a/src/arch/arm/cortex_m3/cortex_m3.cpp +++ b/src/arch/arm/cortex_m3/cortex_m3.cpp @@ -1,5 +1,5 @@ #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "arch/arm/cortex_m3/def.h" +#include "arch/arm/cortex_m3/cortex_m3_defs.hpp" #include "arch/arm/cortex_m3/thumb32_fields.hpp" #include "core/types.hpp" #include "util/logger.hpp" diff --git a/src/arch/toy/cpu.cpp b/src/arch/toy/cpu.cpp index bd383c2..256edf1 100644 --- a/src/arch/toy/cpu.cpp +++ b/src/arch/toy/cpu.cpp @@ -1,4 +1,4 @@ -#include "arch/toy/cpu.h" +#include "arch/toy/cpu.hpp" #include "cpu/cpu.hpp" #include #include diff --git a/src/loader/elf_loader.cpp b/src/loader/elf_loader.cpp index 5861431..9732c8b 100644 --- a/src/loader/elf_loader.cpp +++ b/src/loader/elf_loader.cpp @@ -1,7 +1,7 @@ #include "loader/elf_loader.hpp" #include "autogen/arch_details.hpp" #include "loader/binary_loader.hpp" -#include "loader/utils/def.h" +#include "loader/utils/elf_defs.hpp" #include "loader/utils/elf_parser.hpp" #include diff --git a/src/loader/utils/elf_parser.cpp b/src/loader/utils/elf_parser.cpp index 6f71b5f..84e2f58 100644 --- a/src/loader/utils/elf_parser.cpp +++ b/src/loader/utils/elf_parser.cpp @@ -1,5 +1,5 @@ #include "loader/utils/elf_parser.hpp" -#include "loader/utils/def.h" +#include "loader/utils/elf_defs.hpp" #include namespace micro_forge::loader::utils { diff --git a/test/test_coordinator.cpp b/test/test_coordinator.cpp index e5b7056..e0219e3 100644 --- a/test/test_coordinator.cpp +++ b/test/test_coordinator.cpp @@ -7,7 +7,7 @@ #include "arch/arm/cortex_m3/cortex_m3.hpp" #include "cpu/cpu.hpp" #include "memory/bus.hpp" -#include "util/weak_ptr/weak_ptr_factory.h" +#include "util/weak_ptr/weak_ptr_factory.hpp" using namespace micro_forge; using namespace sim; diff --git a/test/test_cpu.cpp b/test/test_cpu.cpp index 870ee20..0111feb 100644 --- a/test/test_cpu.cpp +++ b/test/test_cpu.cpp @@ -1,7 +1,7 @@ #include -#include "arch/toy/cpu.h" -#include "arch/toy/isa.h" +#include "arch/toy/cpu.hpp" +#include "arch/toy/isa.hpp" #include "memory/flat_memory.hpp" using namespace micro_forge; From c8858545fe4019d81472a82b616251712101bc22 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:00:39 +0800 Subject: [PATCH 04/14] refactor(chips): split stm32f1 into periph/ (devices) and soc/ (assembly) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/chips/stm32f1/ had 11 files flat — 7 peripheral devices mixed with 4 SoC assembly/config files. Split by role: periph/ : stm32f1_{afio,exti,flash,gpio,rcc,timer,usart} (the 7 devices) soc/ : {clock_domains,interrupt_config,memory_bus,peripheral_config, stm32f103_soc} (5 SoC config + assembly; clock_domains is header-only) Finding a device vs an assembly concern no longer needs grep across a flat dir. All #include paths + CMake MICRO_FORGE_SOURCES updated. Default build + 355 ctests + GUI build all green. --- CMakeLists.txt | 22 +++++++++---------- bench/bench_sim.cpp | 2 +- cli/main.cpp | 2 +- examples/gpio_blink/runner.cpp | 2 +- examples/hal_blink/runner.cpp | 2 +- examples/hal_uart/runner.cpp | 2 +- examples/hello_world/runner.cpp | 2 +- examples/hook_demo/runner.cpp | 2 +- examples/systick/runner.cpp | 2 +- gui/main_window.hpp | 2 +- .../stm32f1/{ => periph}/stm32f1_afio.hpp | 0 .../stm32f1/{ => periph}/stm32f1_exti.hpp | 0 .../stm32f1/{ => periph}/stm32f1_flash.hpp | 0 .../stm32f1/{ => periph}/stm32f1_gpio.hpp | 0 .../stm32f1/{ => periph}/stm32f1_rcc.hpp | 0 .../stm32f1/{ => periph}/stm32f1_timer.hpp | 0 .../stm32f1/{ => periph}/stm32f1_usart.hpp | 0 .../chips/stm32f1/{ => soc}/clock_domains.hpp | 0 .../stm32f1/{ => soc}/interrupt_config.hpp | 0 .../chips/stm32f1/{ => soc}/memory_bus.hpp | 0 .../stm32f1/{ => soc}/peripheral_config.hpp | 0 .../chips/stm32f1/{ => soc}/stm32f103_soc.hpp | 16 +++++++------- .../stm32f1/{ => periph}/stm32f1_afio.cpp | 2 +- .../stm32f1/{ => periph}/stm32f1_exti.cpp | 4 ++-- .../stm32f1/{ => periph}/stm32f1_flash.cpp | 2 +- .../stm32f1/{ => periph}/stm32f1_gpio.cpp | 2 +- .../stm32f1/{ => periph}/stm32f1_rcc.cpp | 2 +- .../stm32f1/{ => periph}/stm32f1_timer.cpp | 2 +- .../stm32f1/{ => periph}/stm32f1_usart.cpp | 2 +- .../stm32f1/{ => soc}/interrupt_config.cpp | 2 +- src/chips/stm32f1/{ => soc}/memory_bus.cpp | 2 +- .../stm32f1/{ => soc}/peripheral_config.cpp | 4 ++-- src/chips/stm32f1/{ => soc}/stm32f103_soc.cpp | 8 +++---- src/introspection/introspection.cpp | 2 +- test/test_coordinator.cpp | 2 +- test/test_e2e.cpp | 2 +- test/test_event_bus.cpp | 2 +- test/test_firmware_armcc.cpp | 2 +- test/test_interrupt_roundtrip.cpp | 16 +++++++------- test/test_introspection.cpp | 2 +- test/test_memory_bus.cpp | 2 +- test/test_stm32f103_map.cpp | 2 +- test/test_stm32f103_soc.cpp | 2 +- test/test_stm32f1_periph.cpp | 14 ++++++------ test/test_virtual_clock.cpp | 2 +- 45 files changed, 69 insertions(+), 69 deletions(-) rename include/chips/stm32f1/{ => periph}/stm32f1_afio.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_exti.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_flash.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_gpio.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_rcc.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_timer.hpp (100%) rename include/chips/stm32f1/{ => periph}/stm32f1_usart.hpp (100%) rename include/chips/stm32f1/{ => soc}/clock_domains.hpp (100%) rename include/chips/stm32f1/{ => soc}/interrupt_config.hpp (100%) rename include/chips/stm32f1/{ => soc}/memory_bus.hpp (100%) rename include/chips/stm32f1/{ => soc}/peripheral_config.hpp (100%) rename include/chips/stm32f1/{ => soc}/stm32f103_soc.hpp (85%) rename src/chips/stm32f1/{ => periph}/stm32f1_afio.cpp (97%) rename src/chips/stm32f1/{ => periph}/stm32f1_exti.cpp (96%) rename src/chips/stm32f1/{ => periph}/stm32f1_flash.cpp (96%) rename src/chips/stm32f1/{ => periph}/stm32f1_gpio.cpp (99%) rename src/chips/stm32f1/{ => periph}/stm32f1_rcc.cpp (98%) rename src/chips/stm32f1/{ => periph}/stm32f1_timer.cpp (98%) rename src/chips/stm32f1/{ => periph}/stm32f1_usart.cpp (97%) rename src/chips/stm32f1/{ => soc}/interrupt_config.cpp (95%) rename src/chips/stm32f1/{ => soc}/memory_bus.cpp (95%) rename src/chips/stm32f1/{ => soc}/peripheral_config.cpp (94%) rename src/chips/stm32f1/{ => soc}/stm32f103_soc.cpp (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 685f2a1..4b53ab1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,17 +37,17 @@ set(MICRO_FORGE_SOURCES src/arch/arm/cortex_m3/cortex_m3_reset.cpp src/arch/toy/cpu.cpp src/chips/machine.cpp - src/chips/stm32f1/interrupt_config.cpp - src/chips/stm32f1/memory_bus.cpp - src/chips/stm32f1/peripheral_config.cpp - src/chips/stm32f1/stm32f103_soc.cpp - src/chips/stm32f1/stm32f1_afio.cpp - src/chips/stm32f1/stm32f1_exti.cpp - src/chips/stm32f1/stm32f1_flash.cpp - src/chips/stm32f1/stm32f1_gpio.cpp - src/chips/stm32f1/stm32f1_rcc.cpp - src/chips/stm32f1/stm32f1_timer.cpp - src/chips/stm32f1/stm32f1_usart.cpp + src/chips/stm32f1/soc/interrupt_config.cpp + src/chips/stm32f1/soc/memory_bus.cpp + src/chips/stm32f1/soc/peripheral_config.cpp + src/chips/stm32f1/soc/stm32f103_soc.cpp + src/chips/stm32f1/periph/stm32f1_afio.cpp + src/chips/stm32f1/periph/stm32f1_exti.cpp + src/chips/stm32f1/periph/stm32f1_flash.cpp + src/chips/stm32f1/periph/stm32f1_gpio.cpp + src/chips/stm32f1/periph/stm32f1_rcc.cpp + src/chips/stm32f1/periph/stm32f1_timer.cpp + src/chips/stm32f1/periph/stm32f1_usart.cpp src/cpu/cpu.cpp src/loader/binary_loader.cpp src/loader/elf_loader.cpp diff --git a/bench/bench_sim.cpp b/bench/bench_sim.cpp index 53104be..a29dab5 100644 --- a/bench/bench_sim.cpp +++ b/bench/bench_sim.cpp @@ -10,7 +10,7 @@ // bench_sim [warmup_steps=1_000_000] [measure_steps=10_000_000] [reps=5] // BENCH_SCENARIOS="gpio_iotoggle;uart_printf" (subset; default = all 3) -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "cpu/cpu.hpp" #include "util/perf_stats.hpp" diff --git a/cli/main.cpp b/cli/main.cpp index 2d4a905..cec2f51 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -3,7 +3,7 @@ // stdout ← firmware output (USART) (pipeable / assertable) // stderr ← run status + fault summary (diagnostics) #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "cli/snapshot.hpp" #include "cpu/cpu.hpp" #include "sim/coordinator.hpp" diff --git a/examples/gpio_blink/runner.cpp b/examples/gpio_blink/runner.cpp index 4ef1fd4..c98a5b2 100644 --- a/examples/gpio_blink/runner.cpp +++ b/examples/gpio_blink/runner.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/examples/hal_blink/runner.cpp b/examples/hal_blink/runner.cpp index 9645618..da3c99c 100644 --- a/examples/hal_blink/runner.cpp +++ b/examples/hal_blink/runner.cpp @@ -1,5 +1,5 @@ #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/examples/hal_uart/runner.cpp b/examples/hal_uart/runner.cpp index 6891959..5ddb321 100644 --- a/examples/hal_uart/runner.cpp +++ b/examples/hal_uart/runner.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/examples/hello_world/runner.cpp b/examples/hello_world/runner.cpp index aee3069..2385e75 100644 --- a/examples/hello_world/runner.cpp +++ b/examples/hello_world/runner.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/examples/hook_demo/runner.cpp b/examples/hook_demo/runner.cpp index abe3111..99954fd 100644 --- a/examples/hook_demo/runner.cpp +++ b/examples/hook_demo/runner.cpp @@ -6,7 +6,7 @@ // Plus an RCC diagnostic so you can see where the firmware actually got to. // // ./hook_demo -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "hooks/ring_sink.hpp" #include diff --git a/examples/systick/runner.cpp b/examples/systick/runner.cpp index 5f67c5d..abb6bb0 100644 --- a/examples/systick/runner.cpp +++ b/examples/systick/runner.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/gui/main_window.hpp b/gui/main_window.hpp index 9d5b12b..1508d82 100644 --- a/gui/main_window.hpp +++ b/gui/main_window.hpp @@ -6,7 +6,7 @@ // QThread — that would break deterministic replay (DIRECTIVES §E). #pragma once -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/include/chips/stm32f1/stm32f1_afio.hpp b/include/chips/stm32f1/periph/stm32f1_afio.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_afio.hpp rename to include/chips/stm32f1/periph/stm32f1_afio.hpp diff --git a/include/chips/stm32f1/stm32f1_exti.hpp b/include/chips/stm32f1/periph/stm32f1_exti.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_exti.hpp rename to include/chips/stm32f1/periph/stm32f1_exti.hpp diff --git a/include/chips/stm32f1/stm32f1_flash.hpp b/include/chips/stm32f1/periph/stm32f1_flash.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_flash.hpp rename to include/chips/stm32f1/periph/stm32f1_flash.hpp diff --git a/include/chips/stm32f1/stm32f1_gpio.hpp b/include/chips/stm32f1/periph/stm32f1_gpio.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_gpio.hpp rename to include/chips/stm32f1/periph/stm32f1_gpio.hpp diff --git a/include/chips/stm32f1/stm32f1_rcc.hpp b/include/chips/stm32f1/periph/stm32f1_rcc.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_rcc.hpp rename to include/chips/stm32f1/periph/stm32f1_rcc.hpp diff --git a/include/chips/stm32f1/stm32f1_timer.hpp b/include/chips/stm32f1/periph/stm32f1_timer.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_timer.hpp rename to include/chips/stm32f1/periph/stm32f1_timer.hpp diff --git a/include/chips/stm32f1/stm32f1_usart.hpp b/include/chips/stm32f1/periph/stm32f1_usart.hpp similarity index 100% rename from include/chips/stm32f1/stm32f1_usart.hpp rename to include/chips/stm32f1/periph/stm32f1_usart.hpp diff --git a/include/chips/stm32f1/clock_domains.hpp b/include/chips/stm32f1/soc/clock_domains.hpp similarity index 100% rename from include/chips/stm32f1/clock_domains.hpp rename to include/chips/stm32f1/soc/clock_domains.hpp diff --git a/include/chips/stm32f1/interrupt_config.hpp b/include/chips/stm32f1/soc/interrupt_config.hpp similarity index 100% rename from include/chips/stm32f1/interrupt_config.hpp rename to include/chips/stm32f1/soc/interrupt_config.hpp diff --git a/include/chips/stm32f1/memory_bus.hpp b/include/chips/stm32f1/soc/memory_bus.hpp similarity index 100% rename from include/chips/stm32f1/memory_bus.hpp rename to include/chips/stm32f1/soc/memory_bus.hpp diff --git a/include/chips/stm32f1/peripheral_config.hpp b/include/chips/stm32f1/soc/peripheral_config.hpp similarity index 100% rename from include/chips/stm32f1/peripheral_config.hpp rename to include/chips/stm32f1/soc/peripheral_config.hpp diff --git a/include/chips/stm32f1/stm32f103_soc.hpp b/include/chips/stm32f1/soc/stm32f103_soc.hpp similarity index 85% rename from include/chips/stm32f1/stm32f103_soc.hpp rename to include/chips/stm32f1/soc/stm32f103_soc.hpp index 1378fac..029d71b 100644 --- a/include/chips/stm32f1/stm32f103_soc.hpp +++ b/include/chips/stm32f1/soc/stm32f103_soc.hpp @@ -1,14 +1,14 @@ #pragma once #include "chips/machine.hpp" -#include "chips/stm32f1/clock_domains.hpp" -#include "chips/stm32f1/stm32f1_afio.hpp" -#include "chips/stm32f1/stm32f1_exti.hpp" -#include "chips/stm32f1/stm32f1_flash.hpp" -#include "chips/stm32f1/stm32f1_gpio.hpp" -#include "chips/stm32f1/stm32f1_rcc.hpp" -#include "chips/stm32f1/stm32f1_timer.hpp" -#include "chips/stm32f1/stm32f1_usart.hpp" +#include "chips/stm32f1/soc/clock_domains.hpp" +#include "chips/stm32f1/periph/stm32f1_afio.hpp" +#include "chips/stm32f1/periph/stm32f1_exti.hpp" +#include "chips/stm32f1/periph/stm32f1_flash.hpp" +#include "chips/stm32f1/periph/stm32f1_gpio.hpp" +#include "chips/stm32f1/periph/stm32f1_rcc.hpp" +#include "chips/stm32f1/periph/stm32f1_timer.hpp" +#include "chips/stm32f1/periph/stm32f1_usart.hpp" #include "hooks/event_bus.hpp" #include "memory/flat_memory.hpp" #include "periph/clock_controller.hpp" diff --git a/src/chips/stm32f1/stm32f1_afio.cpp b/src/chips/stm32f1/periph/stm32f1_afio.cpp similarity index 97% rename from src/chips/stm32f1/stm32f1_afio.cpp rename to src/chips/stm32f1/periph/stm32f1_afio.cpp index 4e01e67..079c4be 100644 --- a/src/chips/stm32f1/stm32f1_afio.cpp +++ b/src/chips/stm32f1/periph/stm32f1_afio.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_afio.hpp" +#include "chips/stm32f1/periph/stm32f1_afio.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_exti.cpp b/src/chips/stm32f1/periph/stm32f1_exti.cpp similarity index 96% rename from src/chips/stm32f1/stm32f1_exti.cpp rename to src/chips/stm32f1/periph/stm32f1_exti.cpp index ed20850..e36cd4a 100644 --- a/src/chips/stm32f1/stm32f1_exti.cpp +++ b/src/chips/stm32f1/periph/stm32f1_exti.cpp @@ -1,5 +1,5 @@ -#include "chips/stm32f1/stm32f1_exti.hpp" -#include "chips/stm32f1/stm32f1_afio.hpp" +#include "chips/stm32f1/periph/stm32f1_exti.hpp" +#include "chips/stm32f1/periph/stm32f1_afio.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_flash.cpp b/src/chips/stm32f1/periph/stm32f1_flash.cpp similarity index 96% rename from src/chips/stm32f1/stm32f1_flash.cpp rename to src/chips/stm32f1/periph/stm32f1_flash.cpp index 4390d53..905bea6 100644 --- a/src/chips/stm32f1/stm32f1_flash.cpp +++ b/src/chips/stm32f1/periph/stm32f1_flash.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_flash.hpp" +#include "chips/stm32f1/periph/stm32f1_flash.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_gpio.cpp b/src/chips/stm32f1/periph/stm32f1_gpio.cpp similarity index 99% rename from src/chips/stm32f1/stm32f1_gpio.cpp rename to src/chips/stm32f1/periph/stm32f1_gpio.cpp index 02a06e8..de1710a 100644 --- a/src/chips/stm32f1/stm32f1_gpio.cpp +++ b/src/chips/stm32f1/periph/stm32f1_gpio.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_gpio.hpp" +#include "chips/stm32f1/periph/stm32f1_gpio.hpp" #include "util/logger.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_rcc.cpp b/src/chips/stm32f1/periph/stm32f1_rcc.cpp similarity index 98% rename from src/chips/stm32f1/stm32f1_rcc.cpp rename to src/chips/stm32f1/periph/stm32f1_rcc.cpp index aa0d93f..fabec96 100644 --- a/src/chips/stm32f1/stm32f1_rcc.cpp +++ b/src/chips/stm32f1/periph/stm32f1_rcc.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_rcc.hpp" +#include "chips/stm32f1/periph/stm32f1_rcc.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_timer.cpp b/src/chips/stm32f1/periph/stm32f1_timer.cpp similarity index 98% rename from src/chips/stm32f1/stm32f1_timer.cpp rename to src/chips/stm32f1/periph/stm32f1_timer.cpp index 3106f3b..b438edb 100644 --- a/src/chips/stm32f1/stm32f1_timer.cpp +++ b/src/chips/stm32f1/periph/stm32f1_timer.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_timer.hpp" +#include "chips/stm32f1/periph/stm32f1_timer.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f1_usart.cpp b/src/chips/stm32f1/periph/stm32f1_usart.cpp similarity index 97% rename from src/chips/stm32f1/stm32f1_usart.cpp rename to src/chips/stm32f1/periph/stm32f1_usart.cpp index 8462d6b..05a9e17 100644 --- a/src/chips/stm32f1/stm32f1_usart.cpp +++ b/src/chips/stm32f1/periph/stm32f1_usart.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/stm32f1_usart.hpp" +#include "chips/stm32f1/periph/stm32f1_usart.hpp" #include diff --git a/src/chips/stm32f1/interrupt_config.cpp b/src/chips/stm32f1/soc/interrupt_config.cpp similarity index 95% rename from src/chips/stm32f1/interrupt_config.cpp rename to src/chips/stm32f1/soc/interrupt_config.cpp index 4437f43..3061fe0 100644 --- a/src/chips/stm32f1/interrupt_config.cpp +++ b/src/chips/stm32f1/soc/interrupt_config.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/interrupt_config.hpp" +#include "chips/stm32f1/soc/interrupt_config.hpp" #include "core/mem_literal.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/memory_bus.cpp b/src/chips/stm32f1/soc/memory_bus.cpp similarity index 95% rename from src/chips/stm32f1/memory_bus.cpp rename to src/chips/stm32f1/soc/memory_bus.cpp index 1b4cd87..23e740b 100644 --- a/src/chips/stm32f1/memory_bus.cpp +++ b/src/chips/stm32f1/soc/memory_bus.cpp @@ -1,4 +1,4 @@ -#include "chips/stm32f1/memory_bus.hpp" +#include "chips/stm32f1/soc/memory_bus.hpp" #include "core/mem_literal.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/peripheral_config.cpp b/src/chips/stm32f1/soc/peripheral_config.cpp similarity index 94% rename from src/chips/stm32f1/peripheral_config.cpp rename to src/chips/stm32f1/soc/peripheral_config.cpp index 46c066e..ab3b02e 100644 --- a/src/chips/stm32f1/peripheral_config.cpp +++ b/src/chips/stm32f1/soc/peripheral_config.cpp @@ -1,5 +1,5 @@ -#include "chips/stm32f1/peripheral_config.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/peripheral_config.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "core/mem_literal.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/chips/stm32f1/stm32f103_soc.cpp b/src/chips/stm32f1/soc/stm32f103_soc.cpp similarity index 96% rename from src/chips/stm32f1/stm32f103_soc.cpp rename to src/chips/stm32f1/soc/stm32f103_soc.cpp index 1b311cd..dd1e3f1 100644 --- a/src/chips/stm32f1/stm32f103_soc.cpp +++ b/src/chips/stm32f1/soc/stm32f103_soc.cpp @@ -1,9 +1,9 @@ -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "arch/arm/cortex_m3/cortex_m3.hpp" #include "arch/arm/cortex_m3/cortex_m3_reset.hpp" -#include "chips/stm32f1/interrupt_config.hpp" -#include "chips/stm32f1/memory_bus.hpp" -#include "chips/stm32f1/peripheral_config.hpp" +#include "chips/stm32f1/soc/interrupt_config.hpp" +#include "chips/stm32f1/soc/memory_bus.hpp" +#include "chips/stm32f1/soc/peripheral_config.hpp" #include "hooks/events.hpp" namespace micro_forge::chips::stm32f1 { diff --git a/src/introspection/introspection.cpp b/src/introspection/introspection.cpp index 3962f14..efbbd96 100644 --- a/src/introspection/introspection.cpp +++ b/src/introspection/introspection.cpp @@ -5,7 +5,7 @@ #include "introspection/introspection.hpp" #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "cpu/cpu.hpp" #include diff --git a/test/test_coordinator.cpp b/test/test_coordinator.cpp index e0219e3..301c87e 100644 --- a/test/test_coordinator.cpp +++ b/test/test_coordinator.cpp @@ -1,6 +1,6 @@ #include -#include "chips/stm32f1/clock_domains.hpp" +#include "chips/stm32f1/soc/clock_domains.hpp" #include "sim/coordinator.hpp" #include "sim/virtual_clock.hpp" diff --git a/test/test_e2e.cpp b/test/test_e2e.cpp index 59024ec..26e4f54 100644 --- a/test/test_e2e.cpp +++ b/test/test_e2e.cpp @@ -1,7 +1,7 @@ #include #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/test/test_event_bus.cpp b/test/test_event_bus.cpp index c0289f2..5dbd6fc 100644 --- a/test/test_event_bus.cpp +++ b/test/test_event_bus.cpp @@ -1,7 +1,7 @@ // EventBus wiring tests — confirm GPIO edges AND USART bytes fan into the // SoC's EventBus (and thus any connected RingSink), closing the G3 "声明了 // 从未实例化" gap. EXTI/output behaviour stays intact alongside the bus. -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "hooks/events.hpp" #include "hooks/ring_sink.hpp" diff --git a/test/test_firmware_armcc.cpp b/test/test_firmware_armcc.cpp index 8067810..d7d9a54 100644 --- a/test/test_firmware_armcc.cpp +++ b/test/test_firmware_armcc.cpp @@ -12,7 +12,7 @@ #include #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include #include diff --git a/test/test_interrupt_roundtrip.cpp b/test/test_interrupt_roundtrip.cpp index 6a072e6..71047d9 100644 --- a/test/test_interrupt_roundtrip.cpp +++ b/test/test_interrupt_roundtrip.cpp @@ -1,14 +1,14 @@ #include #include "arch/arm/cortex_m3/cortex_m3.hpp" -#include "chips/stm32f1/clock_domains.hpp" -#include "chips/stm32f1/interrupt_config.hpp" -#include "chips/stm32f1/memory_bus.hpp" -#include "chips/stm32f1/stm32f1_afio.hpp" -#include "chips/stm32f1/stm32f1_exti.hpp" -#include "chips/stm32f1/stm32f1_gpio.hpp" -#include "chips/stm32f1/stm32f1_timer.hpp" -#include "chips/stm32f1/stm32f1_usart.hpp" +#include "chips/stm32f1/soc/clock_domains.hpp" +#include "chips/stm32f1/soc/interrupt_config.hpp" +#include "chips/stm32f1/soc/memory_bus.hpp" +#include "chips/stm32f1/periph/stm32f1_afio.hpp" +#include "chips/stm32f1/periph/stm32f1_exti.hpp" +#include "chips/stm32f1/periph/stm32f1_gpio.hpp" +#include "chips/stm32f1/periph/stm32f1_timer.hpp" +#include "chips/stm32f1/periph/stm32f1_usart.hpp" #include "hooks/events.hpp" #include "memory/bus.hpp" #include "memory/flat_memory.hpp" diff --git a/test/test_introspection.cpp b/test/test_introspection.cpp index d70e30e..ca4aa7d 100644 --- a/test/test_introspection.cpp +++ b/test/test_introspection.cpp @@ -5,7 +5,7 @@ // read — it must not mutate simulator state; (3) on real firmware it observes // the expected advance (state/cycles/pc). #include "introspection/introspection.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" #include "cpu/cpu.hpp" #include diff --git a/test/test_memory_bus.cpp b/test/test_memory_bus.cpp index 6213a93..713cd59 100644 --- a/test/test_memory_bus.cpp +++ b/test/test_memory_bus.cpp @@ -1,6 +1,6 @@ #include -#include "chips/stm32f1/stm32f1_gpio.hpp" +#include "chips/stm32f1/periph/stm32f1_gpio.hpp" #include "core/types.hpp" #include "memory/bus.hpp" #include "memory/flat_memory.hpp" diff --git a/test/test_stm32f103_map.cpp b/test/test_stm32f103_map.cpp index b36fd0c..4ea4764 100644 --- a/test/test_stm32f103_map.cpp +++ b/test/test_stm32f103_map.cpp @@ -1,6 +1,6 @@ #include -#include "chips/stm32f1/memory_bus.hpp" +#include "chips/stm32f1/soc/memory_bus.hpp" #include "core/types.hpp" #include "memory/bus.hpp" #include "memory/flat_memory.hpp" diff --git a/test/test_stm32f103_soc.cpp b/test/test_stm32f103_soc.cpp index 766b28f..c5e3a8a 100644 --- a/test/test_stm32f103_soc.cpp +++ b/test/test_stm32f103_soc.cpp @@ -2,7 +2,7 @@ #include "arch/arm/cortex_m3/cortex_m3.hpp" #include "arch/arm/cortex_m3/cortex_m3_reset.hpp" -#include "chips/stm32f1/stm32f103_soc.hpp" +#include "chips/stm32f1/soc/stm32f103_soc.hpp" using namespace micro_forge; using namespace micro_forge::chips::stm32f1; diff --git a/test/test_stm32f1_periph.cpp b/test/test_stm32f1_periph.cpp index 182d850..b20b3a3 100644 --- a/test/test_stm32f1_periph.cpp +++ b/test/test_stm32f1_periph.cpp @@ -1,12 +1,12 @@ #include -#include "chips/stm32f1/stm32f1_afio.hpp" -#include "chips/stm32f1/stm32f1_exti.hpp" -#include "chips/stm32f1/stm32f1_flash.hpp" -#include "chips/stm32f1/stm32f1_gpio.hpp" -#include "chips/stm32f1/stm32f1_rcc.hpp" -#include "chips/stm32f1/stm32f1_timer.hpp" -#include "chips/stm32f1/stm32f1_usart.hpp" +#include "chips/stm32f1/periph/stm32f1_afio.hpp" +#include "chips/stm32f1/periph/stm32f1_exti.hpp" +#include "chips/stm32f1/periph/stm32f1_flash.hpp" +#include "chips/stm32f1/periph/stm32f1_gpio.hpp" +#include "chips/stm32f1/periph/stm32f1_rcc.hpp" +#include "chips/stm32f1/periph/stm32f1_timer.hpp" +#include "chips/stm32f1/periph/stm32f1_usart.hpp" #include "memory/bus.hpp" #include "memory/flat_memory.hpp" diff --git a/test/test_virtual_clock.cpp b/test/test_virtual_clock.cpp index 4702b3b..2770def 100644 --- a/test/test_virtual_clock.cpp +++ b/test/test_virtual_clock.cpp @@ -1,6 +1,6 @@ #include -#include "chips/stm32f1/clock_domains.hpp" +#include "chips/stm32f1/soc/clock_domains.hpp" #include "sim/virtual_clock.hpp" using namespace micro_forge; From de7a2718f940003bd2fbc4484a31b25d444467e7 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:02:03 +0800 Subject: [PATCH 05/14] =?UTF-8?q?docs(notes):=20038=20=E2=80=94=20director?= =?UTF-8?q?y=20cleanup=20(gui/cli=20top-level,=20hpp=20unify,=20stm32f1=20?= =?UTF-8?q?periph-soc)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- document/notes/038-directory-cleanup.md | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 document/notes/038-directory-cleanup.md diff --git a/document/notes/038-directory-cleanup.md b/document/notes/038-directory-cleanup.md new file mode 100644 index 0000000..1f5761d --- /dev/null +++ b/document/notes/038-directory-cleanup.md @@ -0,0 +1,47 @@ +# 038 · 目录整理四批(GUI / CLI / 后缀 / stm32f1) + +> 日期: 2026-07-07 +> 范围: 物理目录与概念职责对齐;纯重组,零行为变化(唯一 API 变更是 introspection 命名空间 `cli::` → `introspection::`)。 +> 提交: e0dcb9c / 4a7a7cc / d7c80b3 / c885854 +> 验证: 每批 ctest 355/355 + GUI build;批 2 加 CLI SIGINT smoke。 + +## 背景 + +PROJECT-MAP 四层扫描发现一批"物理位置跟概念职责打架"的目录:消费者代码(GUI)坐进核心库 `src/`;库代码(introspection)坐在消费者目录(`src/cli/`);`.h`/`.hpp` 后缀混用(50 个 `.hpp` vs 7 个 legacy `.h`);`stm32f1/` 下 11 个外设器件与 SoC 组装文件平铺。功能都正常(CMake 编译边界已隔干净),但代码组织与 §E「GUI 是 consumer 不是 core」等自身定义不一致。 + +## 目标 + +让每层目录的物理位置跟它的概念职责对齐:核心库代码全在 `src/`,消费者在顶层各占一格,后缀统一,子目录按角色分。 + +## 设计(四批) + +**批 1 · GUI 挪顶层 `gui/`**(e0dcb9c)。`src/gui/` 三个文件移到顶层 `gui/`,新建 `gui/CMakeLists.txt` 持有 Qt 接线(`find_package(Qt6)` + `AUTOMOC` + `target_include_directories PRIVATE ${CMAKE_SOURCE_DIR}`),根 CMakeLists 的内联 if 块换成 `add_subdirectory(gui)`。GUI 跟 `examples/`/`test/`/`bench/` 平级成为第四个顶层消费者目录。 + +**批 2 · CLI/introspection 拆分**(4a7a7cc)。`introspection.{hpp,cpp}` 是核心库代码(在 `MICRO_FORGE_SOURCES`、是 §E 单一事实来源、GUI 也靠它),却坐在 `cli/` 消费者目录。挪到独立库子模块 `src/introspection/` + `include/introspection/`,命名空间 `micro_forge::cli` → `micro_forge::introspection`。CLI 正身(`main`/`snapshot`)挪顶层 `cli/`,`snapshot.hpp` 成为跟 `.cpp` 同目录的内部头。`add_executable(micro-forge ...)` 留在根 CMakeLists(只改源路径),二进制仍是 `build/micro-forge`——README 的 `./build/micro-forge` 路径不断。 + +**批 3 · 后缀统一 + def.h 改名**(d7c80b3)。7 个 legacy `.h` 全改 `.hpp`:`weak_ptr` 系列 3 个、`toy` 2 个、两个 `def.h`。两个 `def.h` 顺手起说得清的名:`arch/arm/cortex_m3/def.h` → `cortex_m3_defs.hpp`(PSR 位标志 + 寄存器表)、`loader/utils/def.h` → `elf_defs.hpp`(ELF 魔数 + `Elf32_*` 结构)。零 `.h` 残留。 + +**批 4 · stm32f1 分 periph/soc**(c885854)。`src/chips/stm32f1/` 11 文件按角色分两层:`periph/`(7 个外设器件 `stm32f1_{afio,exti,flash,gpio,rcc,timer,usart}`)、`soc/`(5 个配置/组装 `{clock_domains,interrupt_config,memory_bus,peripheral_config,stm32f103_soc}`,其中 `clock_domains` header-only)。找一个器件 vs 一个组装逻辑不再 grep 平铺目录。`MICRO_FORGE_SOURCES` 12 条路径 + ~51 处 include 同步。 + +## 关键决策 + +- **GUI 不进 `extension/`**。`extension` 在 05 验收里有专用语义(新 CPU 架构/芯片适配,如 RISC-V/GD32),GUI 不是这类,塞进去会偷换概念。顶层 `gui/` 跟 `examples/test/bench` 对称才是正解。 +- **introspection 命名空间跟着独立**。只挪文件不改命名空间会留半成品(文件在 `src/introspection/` 却叫 `micro_forge::cli`)。`cli::read_introspection` → `introspection::read_introspection`;snapshot 的 `cli::SnapshotExtras`/`write_snapshot_json` 留 `cli`(CLI 专属)。 +- **toy 不删**。曾误判它"没测试",核实 `test/test_cpu.cpp`(`ToyCpuTest`)注册且在 355 测试内、活着。它演示 05 扩展边界,结构不动,只顺带改后缀。 +- **CLI 二进制路径不挪**。`add_executable` 留根 CMakeLists 而非挪 `cli/CMakeLists.txt`,避免 `build/micro-forge` → `build/cli/micro-forge` 断 README 6 处路径。 + +## 陷阱 + +- **`find ... -name x -o -name y` 优先级坑**(批 4 首次 sed)。`-o` 优先级低于隐含 AND,导致 `.hpp` 搜索范围异常、大片文件漏改。改用 `git ls-files '*.hpp' '*.cpp'` 取可靠文件列表。 +- **相对路径 include sed 漏网**(批 3 两次)。`cortex_m3.hpp` 的 `#include "def.h"`、`weak_ptr_factory.hpp` 的 `#include "weak_ptr.h"` 是同目录相对引用,sed 模式带目录前缀匹配不上。教训:sed 前先 grep 全部 include 形式(带前缀 + 相对),分模式处理。 +- **命名空间改动的连锁**(批 2)。`snapshot.cpp` 在 `cli` 命名空间内无限定调用 `read_introspection`/`IntrospectionSnapshot`,符号挪到 `introspection` 后报 `does not name a type`(连带触发三个匿名 helper 的 `-Werror=unused-function`)。修法:`const auto snap = introspection::read_introspection(...)`。 + +## 验证 + +每批独立 `cmake -B build` + `cmake --build build -j$(nproc)` + `ctest --test-dir build`(355/355)+ `cmake -B build-gui -DMICRO_FORGE_GUI=ON` 编 `micro-forge-gui`。批 2 额外 CLI smoke:`timeout -s INT 4 ./build/micro-forge run F103.axf --snapshot-json`,SIGINT 正常退出、stderr 出 `state=Running stop=Interrupted`、JSON 完整(cpu/pc/regs/xpsr/primask 全字段)——证 `read_introspection` 端到端、命名空间改动零行为影响。 + +## 后续 + +- **DIRECTIVES §B 子空间列表**该补 `introspection`(已本机更新,gitignored 不入库)。 +- README 测试数/工具链描述仍脱节(属另一档「README 对齐」,见 PROJECT-MAP §4 第一档)。 +- `set_nvic` 等架构债、probe mode 位置散落——未在本轮范围。 From aa1ac52e896640cacc6977b45f08e4c21fe05ab1 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:20:20 +0800 Subject: [PATCH 06/14] docs(readme): align with v0.2.0 reality (353 tests, GUI landed, tooling, structure) README was stale relative to the codebase: test count said 244 (real 353), the GUI dashboard was listed as a future milestone though G5c shipped it, the moved layout (top-level cli/gui, include/introspection) wasn't reflected, and the coverage/bench/QEMU-oracle tooling was unmentioned. Fixed across both README.md and README.en.md: test count, GUI feature + build instructions, project-structure tree, a Development Tooling section, and a rewritten roadmap that moves EXTI/Timer/USART/GUI to 'already landed'. --- README.en.md | 65 +++++++++++++++++++++++++++++++++++++++------------- README.md | 62 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 32 deletions(-) diff --git a/README.en.md b/README.en.md index 01ac7b6..f95eef3 100644 --- a/README.en.md +++ b/README.en.md @@ -17,9 +17,10 @@ An ARM Cortex-M3 (STM32F103) simulator written in modern C++23 — run and test - **Peripheral Suite** — NVIC, SCB, SysTick, RCC, GPIO (A/B/C), USART1, TIM2, AFIO, FLASH - **Firmware Loading** — ELF loader and raw binary loader - **CLI & Diagnostics** — `micro-forge run` drives firmware with MMIO trace, memory dump, fault recording with context, and `--snapshot-json` JSON state export (CPU / fault / peripherals / recent MMIO) +- **GUI Dashboard** — Optional Qt6 debug dashboard (`-DMICRO_FORGE_GUI=ON`): step / run / reset with visual CPU registers and GPIO output; the simulator runs synchronously on the Qt main thread, preserving single-threaded determinism - **Event Bus & Hooks** — Typed observer subsystem (`Signal`, non-blocking `RingSink`, `EventBus`) emitting `GpioEdge` / `UartByte` events with CPU-cycle timestamps — single-threaded and deterministic, drained offline rather than via a thread pool - **Real-Firmware Proven** — Boots **real Keil/MDK-ARM STM32F103 HAL firmware** end-to-end: reset → `__main` scatter-load → `main` → `HAL_Init` → `SystemClock_Config` (PLL switch) → `MX_GPIO_Init` → `HAL_GPIO_WritePin(PA1)` → `while(1)` with SysTick IRQ -- **Well Tested** — 244 test cases across 19 test files with GoogleTest +- **Well Tested** — 353 test cases across 19 test files with GoogleTest ## Quick Start @@ -69,24 +70,42 @@ ctest --output-on-failure -j$(nproc) > Want to observe pin toggles live? `examples/hook_demo` subscribes to the > event bus and captures PA1 toggles emitted by the GPIO peripheral. +### GUI Dashboard (optional) + +The default build omits the GUI (core library and CLI stay Qt-free). For the +visual debug dashboard: + +```bash +cmake -B build-gui -DMICRO_FORGE_GUI=ON +cmake --build build-gui -j$(nproc) +./build-gui/gui/micro-forge-gui firmware.axf # step / run / reset, inspect registers & GPIO +``` + +The GUI is a pure consumer of the core library, reusing the same +`read_introspection` data; the simulator runs synchronously on the Qt main +thread for deterministic replay. + ## Project Structure ``` include/ - core/ Base types and interfaces (IPeripheral, types) - cpu/ CPU framework (ICore, RegisterFile, ToyCore) - memory/ Memory system (FlatMemory, Bus, Region, bit-band aliases) - periph/ Peripheral abstractions (Device, Gpio, SerialPort, Timer) - hooks/ Event bus (Signal, RingSink, EventBus, GpioEdge/UartByte) - cli/ Command-line interface (snapshot, main) - util/ WeakPtr lifecycle management -src/ Implementation files -test/ GoogleTest suite (244 tests) -examples/ Firmware examples (bare-metal + HAL + Keil/MDK + hook demos) + core/ Base types and interfaces (IPeripheral, types) + cpu/ CPU framework (ICore, RegisterFile, FaultRecord) + memory/ Memory system (FlatMemory, Bus, Region, bit-band aliases) + periph/ Peripheral abstractions (Device, Gpio, SerialPort, Timer) + hooks/ Event bus (Signal, RingSink, EventBus, GpioEdge/UartByte) + introspection/ Structured state export (read_introspection — single source of truth shared by CLI/GUI) + util/ WeakPtr lifecycle management +src/ Core library implementation (arch / chips / cpu / memory / periph / sim / loader / tools / util) +cli/ CLI executable (main, snapshot) — top-level consumer +gui/ Qt6 dashboard executable (main, main_window) — top-level consumer, opt-in +test/ GoogleTest suite (353 tests) +examples/ Firmware examples (bare-metal + HAL + Keil/MDK + hook demos) document/ - milestones/ Version roadmap (v0.1.0 → v1.0.0) - notes/ Design notes by topic -scripts/ Utility scripts + milestones/ Version roadmap (v0.1.0 → v1.0.0) + notes/ Design notes by topic +scripts/ Utility scripts (test-count floor / QEMU oracle / venv gateway) +bench/ Performance benchmarks (with baseline regression gate) ``` ## Examples @@ -101,13 +120,27 @@ scripts/ Utility scripts | `F103` | Real Keil/MDK-ARM STM32F103 HAL GPIO firmware — the end-to-end regression carrier (`examples/F103/MDK-ARM/F103/F103.axf`) | | `hook_demo` | Subscribes to the event bus to capture PA1 toggles live | +## Development Tooling + +- **Coverage** — Build gcov-instrumented binaries with `-DMICRO_FORGE_COVERAGE=ON` and generate reports via `gcovr` (currently lines 81.6% / branches 61.4%). +- **Benchmarks** — `bench/` with a baseline regression gate; the perf campaign lifted GPIO / USART / TIM instruction throughput by 51-57%. +- **QEMU differential oracle** — `scripts/qemu_cortex_m3_oracle.sh` checks instruction semantics (SDIV / UDIV / ADC / SBC + xPSR) against real QEMU, byte-for-byte. +- **Test-count floor** — `scripts/check_test_count.sh` pins the baseline so refactors can't silently drop tests. + ## Roadmap See [document/milestones/](document/milestones/) for the full version roadmap. -Already landed: the **`micro-forge run` CLI** with `--snapshot-json` state export and MMIO tracing, the **Cortex-M3 correctness foundation** (interrupt preemption, MSP/PSP dual-stack, PRIGROUP, NVIC priority cache, bit-band aliases), the **Thumb-2 instruction-coverage fix** that lets real Keil/MDK-ARM HAL firmware boot end-to-end, and the **event-bus hooks subsystem**. +Already landed: + +- **CLI & observability** — `micro-forge run` + `--snapshot-json` + `--trace-mmio`; structured introspection is the single source of truth shared by CLI and GUI +- **Cortex-M3 correctness foundation** — interrupt preemption and nesting, MSP/PSP dual-stack, PRIGROUP priority grouping, NVIC priority cache, bit-band alias regions +- **Full Thumb-2 coverage** — real Keil/MDK-ARM HAL firmware boots end-to-end +- **Three interrupt paths end-to-end** — Timer UIF / EXTI GPIO edge / USART RXNE, all via the common `raise_irq` channel +- **Event-bus hooks** — typed observers with CPU-cycle timestamps +- **Qt6 GUI dashboard** — step / run / reset, visual CPU registers and GPIO (opt-in) -Key milestones ahead: full exception semantics tail-chaining, EXTI / Timer-IRQ / USART-RX-IRQ end-to-end paths, DMA / SPI / FLASH depth, extended HAL peripheral coverage, and a GUI debug dashboard. +Key milestones ahead: DMA / SPI / FLASH peripheral depth, extended HAL peripheral coverage, and more GUI debug panels (full fault detail, serial terminal, interrupt-system visualization). ## License diff --git a/README.md b/README.md index 55608b1..4beca72 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,10 @@ - **外设套件** —— NVIC、SCB、SysTick、RCC、GPIO(A/B/C)、USART1、TIM2、AFIO、FLASH - **固件加载** —— ELF 加载器和原始二进制加载器 - **CLI 与诊断** —— `micro-forge run` 驱动固件运行,支持 MMIO 追踪、内存转储、带上下文的故障记录,以及 `--snapshot-json` JSON 状态导出(CPU / 故障 / 外设 / 近期 MMIO) +- **GUI 仪表盘** —— 可选的 Qt6 调试仪表盘(`-DMICRO_FORGE_GUI=ON`),单步 / 运行 / 复位,可视化 CPU 寄存器与 GPIO 输出;模拟器同步跑在 Qt 主线程,保持单线程确定性 - **事件总线与 Hooks** —— 类型化观察者子系统(`Signal`、非阻塞 `RingSink`、`EventBus`),发射带 CPU 周期时戳的 `GpioEdge` / `UartByte` 事件 —— 单线程、确定性,离线 drain 而非线程池 - **真实固件验证** —— 端到端跑通**真实 Keil/MDK-ARM STM32F103 HAL 固件**:reset → `__main` scatter-load → `main` → `HAL_Init` → `SystemClock_Config`(切 PLL)→ `MX_GPIO_Init` → `HAL_GPIO_WritePin(PA1)` → `while(1)`,SysTick 中断正常 -- **测试完善** —— 19 个测试文件共 244 个 GoogleTest 用例 +- **测试完善** —— 19 个测试文件共 353 个 GoogleTest 用例 ## 快速开始 @@ -67,24 +68,39 @@ ctest --output-on-failure -j$(nproc) > 想实时观察引脚翻转?`examples/hook_demo` 订阅事件总线, > 捕获 GPIO 外设发出的 PA1 翻转事件。 +### GUI 仪表盘(可选) + +默认构建不含 GUI(核心库与 CLI 零 Qt 依赖)。需要可视化调试仪表盘时: + +```bash +cmake -B build-gui -DMICRO_FORGE_GUI=ON +cmake --build build-gui -j$(nproc) +./build-gui/gui/micro-forge-gui firmware.axf # 单步 / 运行 / 复位,看寄存器与 GPIO +``` + +GUI 是核心库的纯消费者,复用 `read_introspection` 同一份数据;模拟器同步跑在 Qt 主线程,确定性可重放。 + ## 项目结构 ``` include/ - core/ 基础类型和接口(IPeripheral、types) - cpu/ CPU 框架(ICore、RegisterFile、ToyCore) - memory/ 内存系统(FlatMemory、Bus、Region、位带别名) - periph/ 外设抽象(Device、Gpio、SerialPort、Timer) - hooks/ 事件总线(Signal、RingSink、EventBus、GpioEdge/UartByte) - cli/ 命令行界面(snapshot、main) - util/ WeakPtr 生命周期管理 -src/ 实现文件 -test/ GoogleTest 测试套件(244 个测试) -examples/ 固件示例(裸机 + HAL + Keil/MDK + hook 演示) + core/ 基础类型和接口(IPeripheral、types) + cpu/ CPU 框架(ICore、RegisterFile、FaultRecord) + memory/ 内存系统(FlatMemory、Bus、Region、位带别名) + periph/ 外设抽象(Device、Gpio、SerialPort、Timer) + hooks/ 事件总线(Signal、RingSink、EventBus、GpioEdge/UartByte) + introspection/ 结构化状态导出(read_introspection —— CLI/GUI 共享的单一事实来源) + util/ WeakPtr 生命周期管理 +src/ 核心库实现(arch / chips / cpu / memory / periph / sim / loader / tools / util) +cli/ CLI 可执行(main、snapshot)—— 顶层消费者 +gui/ Qt6 仪表盘可执行(main、main_window)—— 顶层消费者,opt-in +test/ GoogleTest 测试套件(353 个测试) +examples/ 固件示例(裸机 + HAL + Keil/MDK + hook 演示) document/ - milestones/ 版本路线图(v0.1.0 → v1.0.0) - notes/ 按主题组织的设计笔记 -scripts/ 工具脚本 + milestones/ 版本路线图(v0.1.0 → v1.0.0) + notes/ 按主题组织的设计笔记 +scripts/ 工具脚本(测试数地板门 / QEMU oracle / venv 网关) +bench/ 性能基准(含 baseline 回归软门) ``` ## 示例 @@ -99,13 +115,27 @@ scripts/ 工具脚本 | `F103` | 真实 Keil/MDK-ARM STM32F103 HAL GPIO 固件 —— 端到端回归载体(`examples/F103/MDK-ARM/F103/F103.axf`) | | `hook_demo` | 订阅事件总线,实时捕获 PA1 翻转 | +## 开发工具链 + +- **覆盖率** —— `-DMICRO_FORGE_COVERAGE=ON` 编 gcov 插桩版,配 `gcovr` 出报告(当前 lines 81.6% / branches 61.4%)。 +- **性能基准** —— `bench/` 附 baseline 回归软门;perf 战役让 GPIO / USART / TIM 指令吞吐 +51-57%。 +- **QEMU 差分 oracle** —— `scripts/qemu_cortex_m3_oracle.sh` 跟真机 QEMU 逐字对照指令语义(SDIV / UDIV / ADC / SBC + xPSR)。 +- **测试数地板门** —— `scripts/check_test_count.sh` 锁基线,防重构静默吞测试。 + ## 路线图 完整版本路线图见 [document/milestones/](document/milestones/)。 -已落地:**`micro-forge run` CLI**(含 `--snapshot-json` 状态导出和 MMIO 追踪)、**Cortex-M3 正确性基础**(中断抢占、MSP/PSP 双栈、PRIGROUP、NVIC 优先级缓存、位带别名)、**Thumb-2 指令覆盖修复**(让真实 Keil/MDK-ARM HAL 固件端到端跑通),以及**事件总线 hooks 子系统**。 +已落地: + +- **CLI 与可观测性** —— `micro-forge run` + `--snapshot-json` + `--trace-mmio`;结构化 introspection 作为 CLI / GUI 共享的单一事实来源 +- **Cortex-M3 正确性基础** —— 中断抢占与嵌套、MSP/PSP 双栈、PRIGROUP 优先级分组、NVIC 优先级缓存、位带别名区 +- **Thumb-2 指令全覆盖** —— 真实 Keil/MDK-ARM HAL 固件端到端跑通 +- **三条中断通道端到端** —— Timer UIF / EXTI GPIO 边沿 / USART RXNE,全经公共 `raise_irq` 通道 +- **事件总线 hooks** —— 类型化观察者,带 CPU 周期时戳 +- **Qt6 GUI 仪表盘** —— 单步 / 运行 / 复位,可视化 CPU 寄存器与 GPIO(opt-in) -后续关键里程碑:完整的异常语义尾链(tail-chaining)、EXTI / Timer-IRQ / USART-RX-IRQ 端到端通路、DMA / SPI / FLASH 深化、HAL 外设覆盖扩展,以及 GUI 调试仪表盘。 +后续关键里程碑:DMA / SPI / FLASH 外设深化、HAL 外设覆盖扩展、GUI 调试面板继续兑现(完整 fault 详情、串口终端、中断系统可视化)。 ## 许可证 From 8f68d623454e5e8c60e607b0447f547464b81f9b Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:27:53 +0800 Subject: [PATCH 07/14] feat(cli): dump-mem subcommand + fault summary with opcode/addr/bus_error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the two v0.2.0 acceptance gaps from milestone 01: * 'micro-forge dump-mem --addr A [--len N]' — loads firmware (sharing a load_firmware helper with 'run') and dumps a memory window via the existing tools::memory_dump. Verified: F103.axf vector table head dumps correctly (0x20000670 SP, 0x08000189 reset handler). * fault summary now prints the instruction opcode (16/32-bit), and when present the access_addr (+width) and bus_error — the data was already in FaultRecord, the CLI just wasn't surfacing it. Verified opcode path with an illegal-instruction binary; access_addr/bus_error branches are optional-gated (data-access faults only) and code-reviewed. Default build + 355 ctests green. --- cli/main.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 15 deletions(-) diff --git a/cli/main.cpp b/cli/main.cpp index cec2f51..a495aef 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -7,6 +7,7 @@ #include "cli/snapshot.hpp" #include "cpu/cpu.hpp" #include "sim/coordinator.hpp" +#include "tools/memory_dump.hpp" #include "tools/mmio_trace.hpp" #include @@ -77,6 +78,40 @@ const char* fault_kind_name(cpu::CPU::CPUError k) { return "Unknown"; } +const char* bus_error_name(BusError b) { + switch (b) { + case BusError::Unmapped: return "Unmapped"; + case BusError::Unaligned: return "Unaligned"; + case BusError::ReadOnly: return "ReadOnly"; + case BusError::InvalidDevice: return "InvalidDevice"; + case BusError::RegionOverlap: return "RegionOverlap"; + case BusError::OutOfRange: return "OutOfRange"; + case BusError::PeripheralFault: return "PeripheralFault"; + } + return "Unknown"; +} + +const char* width_name(Width w) { + switch (w) { + case Width::Byte: return "byte"; + case Width::HalfWord: return "halfword"; + case Width::Word: return "word"; + } + return "?"; +} + +// Create the SoC and load firmware (ELF or raw binary). Shared by `run` and +// `dump-mem` so the loading path lives in exactly one place. +std::expected, std::string> load_firmware( + const std::vector& data, uint32_t base) { + auto soc = Stm32f103Soc::create(); + if (!soc) return std::unexpected(soc.error()); + auto lr = is_elf(data) ? (*soc)->load_elf(data) + : (*soc)->load_bin(base, data); + if (!lr) return std::unexpected(lr.error()); + return std::move(*soc); +} + const char* run_result_name(sim::RunResult r) { switch (r) { case sim::RunResult::Running: @@ -97,7 +132,10 @@ void print_usage() { "usage: micro-forge [options]\n" " run [--chip stm32f103] [--base 0x08000000]\n" " [--max-steps N] [--trace-mmio] [--snapshot-json FILE]\n" - " (runs forever by default; Ctrl+C stops with a report)\n"); + " (runs forever by default; Ctrl+C stops with a report)\n" + " dump-mem --addr 0x20000000 [--len 256]\n" + " [--chip stm32f103] [--base 0x08000000]\n" + " (loads firmware, dumps a memory window to stdout)\n"); } struct RunOptions { @@ -178,9 +216,10 @@ int cmd_run(int argc, char** argv) { return 1; } - auto soc = Stm32f103Soc::create(); + auto soc = load_firmware(data, opt.base); if (!soc) { - std::fprintf(stderr, "SoC create failed: %s\n", soc.error().c_str()); + std::fprintf(stderr, "firmware load failed: %s\n", + soc.error().c_str()); return 1; } @@ -190,14 +229,6 @@ int cmd_run(int argc, char** argv) { usart_out += static_cast(e.byte); }); - std::expected lr = - is_elf(data) ? (*soc)->load_elf(data) - : (*soc)->load_bin(opt.base, data); - if (!lr) { - std::fprintf(stderr, "firmware load failed: %s\n", lr.error().c_str()); - return 1; - } - // B3: collect recent MMIO accesses into a capped ring for diagnostics. std::vector events; constexpr size_t kEventCap = 256; @@ -243,11 +274,30 @@ int cmd_run(int argc, char** argv) { if (cm3.IsValid()) { const auto& fr = cm3->last_fault(); if (fr.has_value()) { - std::fprintf( - stderr, "[fault] kind=%s pc=0x%08X lr=0x%08X sp=0x%08X%s\n", + std::fprintf(stderr, + "[fault] kind=%s pc=0x%08X lr=0x%08X sp=0x%08X\n", fault_kind_name(fr->kind), static_cast(fr->pc), - static_cast(fr->lr), static_cast(fr->sp), - fr->is_32bit ? " (32-bit insn)" : ""); + static_cast(fr->lr), static_cast(fr->sp)); + if (fr->is_32bit) { + std::fprintf(stderr, " insn=0x%04X 0x%04X (32-bit)\n", + fr->opcode16, fr->opcode16_2); + } else { + std::fprintf(stderr, " insn=0x%04X (16-bit)\n", + fr->opcode16); + } + if (fr->access_addr) { + std::fprintf(stderr, " access=0x%08X", + static_cast(*fr->access_addr)); + if (fr->access_width) { + std::fprintf(stderr, " (%s)", + width_name(*fr->access_width)); + } + std::fputc('\n', stderr); + } + if (fr->bus_error) { + std::fprintf(stderr, " bus_error=%s\n", + bus_error_name(*fr->bus_error)); + } } } @@ -279,6 +329,78 @@ int cmd_run(int argc, char** argv) { return bad ? 1 : 0; } +int cmd_dump_mem(int argc, char** argv) { + std::string chip = "stm32f103", firmware; + uint32_t base = 0x08000000, addr = 0, len = 256; + bool addr_set = false; + for (int i = 0; i < argc; ++i) { + std::string a = argv[i]; + auto next = [&]() -> const char* { + return (i + 1 < argc) ? argv[++i] : nullptr; + }; + if (a == "--chip") { + const char* v = next(); + if (!v) { std::fprintf(stderr, "--chip needs a value\n"); return 2; } + chip = v; + } else if (a == "--base") { + const char* v = next(); + if (!v) { std::fprintf(stderr, "--base needs a value\n"); return 2; } + base = static_cast(std::strtoul(v, nullptr, 0)); + } else if (a == "--addr") { + const char* v = next(); + if (!v) { std::fprintf(stderr, "--addr needs a value\n"); return 2; } + addr = static_cast(std::strtoul(v, nullptr, 0)); + addr_set = true; + } else if (a == "--len") { + const char* v = next(); + if (!v) { std::fprintf(stderr, "--len needs a value\n"); return 2; } + len = static_cast(std::strtoul(v, nullptr, 0)); + } else if (!a.empty() && a[0] != '-') { + if (firmware.empty()) { + firmware = a; + } else { + std::fprintf(stderr, "unexpected positional arg: %s\n", a.c_str()); + return 2; + } + } else { + std::fprintf(stderr, "unknown option: %s\n", a.c_str()); + print_usage(); + return 2; + } + } + if (chip != "stm32f103") { + std::fprintf(stderr, "unsupported chip '%s' (only stm32f103)\n", chip.c_str()); + return 2; + } + if (firmware.empty()) { + std::fprintf(stderr, "missing firmware path\n"); + print_usage(); + return 2; + } + if (!addr_set) { + std::fprintf(stderr, "missing --addr (e.g. --addr 0x20000000)\n"); + return 2; + } + + auto data = read_file(firmware); + if (data.empty()) { + std::fprintf(stderr, "cannot read firmware: %s\n", firmware.c_str()); + return 1; + } + auto soc = load_firmware(data, base); + if (!soc) { + std::fprintf(stderr, "firmware load failed: %s\n", soc.error().c_str()); + return 1; + } + + // Dump the requested memory window to stdout via the shared tool. + tools::memory_dump(*(*soc)->machine().bus, addr, len, + [](std::string_view sv) { + std::fwrite(sv.data(), 1, sv.size(), stdout); + }); + return 0; +} + } // namespace int main(int argc, char** argv) { @@ -291,6 +413,9 @@ int main(int argc, char** argv) { if (sub == "run") { return cmd_run(argc - 2, argv + 2); } + if (sub == "dump-mem") { + return cmd_dump_mem(argc - 2, argv + 2); + } if (sub == "-h" || sub == "--help" || sub == "help") { print_usage(); return 0; From d5177a1f3e6d6beae34651354dd39a5a4f6ec6bd Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:31:22 +0800 Subject: [PATCH 08/14] release(v0.2.0): VERSION bump, CHANGELOG, support matrix, install rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release-engineering minimum to cut v0.2.0: * project(VERSION) 0.1.0 -> 0.2.0 * CHANGELOG.md (Keep-a-Changelog) covering everything since v0.1.0 * document/SUPPORT.md — explicit support matrix + non-goals (milestone 05) * cmake --install rules: core lib + CLI + public headers (GUI conditional) * README links to CHANGELOG and support matrix (zh + en) Verified: cmake --install --prefix /tmp/mf-install deploys 109 files (bin/ micro-forge, lib/, include/ with the new periph/soc layout). Default build + 355 ctests green. No CPack — teaching/portfolio use, not distribution. Tag and push deferred until review. --- CHANGELOG.md | 60 +++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 18 +++++++++++++- README.en.md | 2 +- README.md | 2 +- document/SUPPORT.md | 58 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 document/SUPPORT.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..42ab52c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,60 @@ +# Changelog + +All notable changes to micro-forge are documented here. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.2.0] - 2026-07-07 + +### Added +- **CLI runner** — `micro-forge run` with `--snapshot-json` (5-region JSON state + export: CPU / fault / run / peripherals / events), `--trace-mmio`, `--max-steps`, + and `--base` for raw binaries. +- **`micro-forge dump-mem`** subcommand — loads firmware and dumps a memory window. +- **Structured introspection API** (`read_introspection`) — the single source of + truth consumed by both the CLI JSON serializer and the GUI dashboard. +- **Cortex-M3 correctness foundation** — interrupt preemption and nesting, + MSP/PSP dual-stack, PRIGROUP priority grouping, NVIC lazy priority cache, + bit-band alias regions (SRAM `0x22……` + peripheral `0x42……`). +- **Full Thumb-2 instruction coverage** for the ARMv7-M base profile; real + Keil/MDK-ARM STM32F103 HAL firmware boots end-to-end. +- **Three end-to-end interrupt paths** — Timer UIF, EXTI GPIO edge, USART RXNE + — all wired through a common `raise_irq` channel. +- **Event-bus hooks subsystem** — typed `Signal`, non-blocking `RingSink`, + `EventBus`, emitting cycle-timestamped `GpioEdge` / `UartByte` events. +- **Qt6 GUI dashboard** (opt-in, `-DMICRO_FORGE_GUI=ON`) — step / run / reset, + visual CPU registers and GPIO output. +- **Coverage pipeline** (`-DMICRO_FORGE_COVERAGE=ON` + `gcovr`) — lines 81.6% / + branches 61.4% / functions 90.2%. +- **QEMU differential oracle** (`scripts/qemu_cortex_m3_oracle.sh`) — checks + SDIV/UDIV/ADC/SBC + xPSR semantics against real QEMU. +- **Test-count floor gate** (`scripts/check_test_count.sh`) — pins the baseline + so refactors can't silently drop tests. +- **Install rules** — `cmake --install` deploys the library, CLI, and headers. +- Firmware corpus: 12 AC6 `.axf` images (3 examples × `-O0/-O2/-Oz`) for + optimization-level regression. + +### Changed +- **Project layout cleanup** — GUI and CLI moved to top-level consumer + directories (`gui/`, `cli/`); introspection split into its own library module + (`src/introspection/` + `include/introspection/`, namespace + `micro_forge::introspection`); `src/chips/stm32f1/` split into `periph/` + (devices) and `soc/` (assembly); all headers unified to `.hpp`; the two + generic `def.h` renamed to `cortex_m3_defs.hpp` and `elf_defs.hpp`. +- Test count 217 → 353 product tests (+ 2 meta-guards). + +### Fixed +- Thumb-2 decoding gaps that blocked real HAL firmware (`LDR.W` PC-literal, + `BLX Rm` not setting LR, `ADR.W`, `SUB.W/SUBW` plain imm12, load/store + `hw1[7]` addressing, shifted-reg `CMP/CMN` clobbering PC, `B.N` self-loop). +- `SDIV/0` returns 0 (initial implementation returned INT_MIN; corrected against + the QEMU oracle); `ADC/SBC` C/V carry flags; 32-bit `ADC.W`/`SBC.W` + shifted-register operands; INT_MIN / -1 saturation guards. + +## [0.1.0] - 2026-05-20 +- Initial release: Cortex-M3 Thumb/Thumb-2 decoder, FlatMemory + Bus + Region + address routing, NVIC / SysTick / SCB, RCC / GPIO (A/B/C) / USART1 / TIM2 / + AFIO / FLASH, ELF + BIN loaders, 217 GoogleTest cases + 4 end-to-end + examples (hello / gpio_blink / systick / HAL UART). diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b53ab1..f7ca72f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.25) project(micro-forge - VERSION 0.1.0 + VERSION 0.2.0 LANGUAGES CXX ) @@ -99,3 +99,19 @@ add_subdirectory(bench) if(MICRO_FORGE_GUI) add_subdirectory(gui) endif() + +# ── Install rules (release engineering) ── +# The core static library, CLI runner, and public headers install cleanly via +# `cmake --install`. GUI is installed only when built. No CPack packaging — +# this project targets teaching/portfolio use, not distribution packages. +include(GNUInstallDirs) +install(TARGETS micro_forge + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(TARGETS micro-forge + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.hpp") +if(MICRO_FORGE_GUI) + install(TARGETS micro-forge-gui + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/README.en.md b/README.en.md index f95eef3..800b3e6 100644 --- a/README.en.md +++ b/README.en.md @@ -129,7 +129,7 @@ bench/ Performance benchmarks (with baseline regression gate) ## Roadmap -See [document/milestones/](document/milestones/) for the full version roadmap. +See [document/milestones/](document/milestones/) for the full version roadmap; the v0.2.0 [support matrix](document/SUPPORT.md) and [CHANGELOG](CHANGELOG.md) cover what's supported and what changed. Already landed: diff --git a/README.md b/README.md index 4beca72..f1d2a13 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ bench/ 性能基准(含 baseline 回归软门) ## 路线图 -完整版本路线图见 [document/milestones/](document/milestones/)。 +完整版本路线图见 [document/milestones/](document/milestones/);v0.2.0 支持范围见 [支持矩阵](document/SUPPORT.md),变更历史见 [CHANGELOG](CHANGELOG.md)。 已落地: diff --git a/document/SUPPORT.md b/document/SUPPORT.md new file mode 100644 index 0000000..bbf85ff --- /dev/null +++ b/document/SUPPORT.md @@ -0,0 +1,58 @@ +# micro-forge 支持矩阵 · v0.2.0 + +> 本文明确 micro-forge v0.2.0 **支持什么、不支持什么**。决策依据见 +> [`document/milestones/00-v1-roadmap.md`](milestones/00-v1-roadmap.md) 与 +> [`05-extension-architecture.md`](milestones/05-extension-architecture.md)。 + +## CPU / 指令集 + +- **支持**:ARM **Cortex-M3**(ARMv7-M base profile,无 DSP 扩展)。 +- **指令集**:Thumb-16 全集 + Thumb-32 全集(ARMv7-M 范围)。ARMv7E-M DSP 指令 + (QADD / UMAAL / PKH / SEL / SXTAH 等)在 M3 上本应 `UndefinedInstruction`, + 已加 clean-fault 门禁。 +- **异常/中断**:抢占与嵌套、PRIMASK / BASEPRI / FAULTMASK、PRIGROUP 优先级分组、 + MSP/PSP 双栈与 EXC_RETURN、bit-band 别名区。 +- **非目标**:tail-chaining(同步模拟器天然退化,见 notes 005)、late-arrival + (同理)。RISC-V / AVR / 8051 / Cortex-M4/M7(v1.0 不实现,但架构边界已预留)。 + +## 芯片 / SoC + +- **支持**:**STM32F103**(首个 SoC package)。 +- **非目标**:GD32 或其他 STM32 变体(v1.0 不实现,`SoC package` 边界已留)。 + +## 外设(STM32F103) + +| 外设 | 状态 | 说明 | +|------|------|------| +| NVIC | 完整 | 抢占/嵌套/PRIMASK/BASEPRI/PRIGROUP,lazy priority cache | +| SCB | 完整 | VTOR / AIRCR 写回调注入 CPU | +| SysTick | 完整 | CTRL / LOAD / VAL,经 SHPR 查询优先级 | +| GPIO A/B/C | 完整 | ODR/IDR,bit-band 别名,边沿 emit 到事件总线 | +| USART1 | TX polling + RX 注入 | RXNEIE 中断;TXEIE 跳过(TX 即时,无延迟可消耗) | +| TIM2 | UIF → NVIC E2E | PSC/ARR/CNT + VirtualClock 联动 | +| RCC | 轮询友好 | 就绪标志立即就绪、SR 永不 BUSY | +| AFIO | 完整 | EXTICR 路由到 EXTI | +| EXTI | 完整 | IMR/EMR/RTSR/FTSR/SWIER/PR,线 → IRQ 路由 | +| FLASH | **外壳 only** | 寄存器读写 real;**无** unlock/erase/program 状态机 | +| SPI / I2C / ADC / DMA | **未实现** | 零代码(待具体固件需求驱动) | + +## 工具链 + +- **编译**:GCC-14+(C++23 严格),CMake 3.25+,`-Wall -Wextra -Werror`。 +- **测试**:GoogleTest,353 产品用例 + 2 meta-guard;E2E 含真实 Keil/MDK-ARM HAL 固件。 +- **覆盖率**:gcov + gcovr(`-DMICRO_FORGE_COVERAGE=ON`),lines 81.6% / branches 61.4%。 +- **正确性**:QEMU 差分 oracle(`qemu-system-gnuarmeless` mps2-an385 + gdbstub)。 +- **CI**:GitHub Actions,GCC-14 build+test 与交叉编译 E2E 两条流水线。 + +## 固件格式 + +- **ELF32**:ARM machine、little-endian(loader 校验 magic / class / data / machine)。 +- **Raw binary**:`--base` 指定加载地址。 + +## 设计上的非目标(v1.0) + +- **周期精确**(cycle-accurate)模拟 —— 明确不追。 +- **GDB remote protocol** / 交互式调试器协议 —— v0.2 仅 file/stdout JSON snapshot。 +- **HTTP / WebSocket / MCP** 服务接口 —— 不实现常驻服务。 +- **多线程模拟** —— 单线程确定性是设计目标(确定性可重放)。 +- **插件 ABI 稳定** —— v1.0 只承诺 C++ package 级扩展边界清晰。 From 6ba2f6a337ba6027ba8204d7ee9ce3f3dc4ccfa7 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 13:32:08 +0800 Subject: [PATCH 09/14] =?UTF-8?q?docs(notes):=20039=20=E2=80=94=20v0.2.0?= =?UTF-8?q?=20release=20prep=20(README=20align,=20dump-mem,=20release=20en?= =?UTF-8?q?gineering)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- document/notes/039-v0.2.0-release-prep.md | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 document/notes/039-v0.2.0-release-prep.md diff --git a/document/notes/039-v0.2.0-release-prep.md b/document/notes/039-v0.2.0-release-prep.md new file mode 100644 index 0000000..7b8d353 --- /dev/null +++ b/document/notes/039-v0.2.0-release-prep.md @@ -0,0 +1,35 @@ +# 039 · v0.2.0 发版准备三波 + +> 日期: 2026-07-07 +> 分支: `release/v0.2.0-prep`(基于 main `de7a271`) +> 提交: aa1ac52 / 8f68d62 / d5177a1 +> 状态: **停在 commit,等审查。未 push、未切 tag。** +> 验证: build + 355 ctest + 三个 smoke(dump-mem / fault 摘要 / cmake --install)。 + +## 背景 + +PROJECT-MAP §2.4 盘点出三类「项目基建没对齐」:README 与代码严重脱节(测试数写 244 实际 353、GUI 被列在「未来里程碑」但已落地、coverage/bench/oracle 工具链只字未提);milestone 01 的 v0.2.0 验收有两处缺口(`dump-mem` 子命令、fault 摘要缺 opcode/地址/BusError);发版工程六件套全空(VERSION 写死 0.1.0、无 install、无 CHANGELOG、无 support-matrix、无 v0.2.0 tag)。本批把这些一次收拾干净,停在 commit 等用户审查后再切 tag/push。 + +## 三波 + +**第一波 · README 全量对齐**(aa1ac52)。中英同步:测试数 244→353(4 处);GUI 从「后续里程碑」挪到 Features 段(含 `-DMICRO_FORGE_GUI=ON` 编译说明);新增「开发工具链」段(coverage 81.6%/61.4%、bench +51-57%、QEMU oracle、测试地板门);项目结构图重画(顶层 cli/gui/bench、include/introspection、删 include/cli);Roadmap 重写(EXTI/Timer/USART 三通道 + GUI 移到「已落地」,删已不做的 tail-chaining)。 + +**第二波 · v0.2.0 验收缺口**(8f68d62)。 +- `micro-forge dump-mem --addr A [--len N]`:复用新抽的 `load_firmware` helper(`run` 也改用它,去重 create+load),调 `tools::memory_dump` 输出 hex+ASCII。 +- fault 摘要增强:补指令 opcode(16/32-bit)、可选 access_addr (+width)、可选 bus_error。数据本就在 `FaultRecord`,CLI 之前没取。 + +**第三波 · 发版工程最小包**(d5177a1)。`project(VERSION)` 0.1.0→0.2.0;CHANGELOG.md(Keep-a-Changelog,覆盖 v0.1.0→v0.2.0 全部 Added/Changed/Fixed);document/SUPPORT.md(CPU/芯片/外设/工具链支持矩阵 + 非目标,05 验收要求);最小 install 规则(核心库 + CLI + 公共头,GUI 条件 install,无 CPack);README 加 CHANGELOG/SUPPORT 链接。 + +## 验证 + +- build + 355/355 ctest 全绿。 +- **dump-mem smoke**:`dump-mem F103.axf --addr 0x08000000 --len 16` 输出向量表头 `70 06 00 20 89 01 00 08 …`(初始 SP 0x20000670、reset handler 0x08000189),格式正确。 +- **fault 摘要 smoke**:非法指令 BIN 触发 fault,新摘要打出 `insn=0xFFFF 0xFFFF (32-bit)`。opcode 路径实测通过。 +- **install smoke**:`cmake --install build --prefix /tmp/mf-install` 装了 109 文件(bin/micro-forge、lib/、include/ 按新 periph/soc 结构)。 + +## 待审查决策(给用户) + +1. **切 tag / push**:outward 动作,本轮未做。审查通过后 `git tag v0.2.0` + push。 +2. **install 完整性**:当前 install 装核心库 + CLI + `include/` 下 `.hpp`,但**漏 `autogen/arch_details.hpp`**(configure_file 生成在 binary dir,不在 include/)。教学/单体使用够;若要让人 `cmake --install` 后当库链接,需补生成头的 install 规则。 +3. **access_addr/bus_error 分支**:fault 摘要这两行是 optional-gated(仅 DataAccessFault 类才填),靠代码审查,**未端到端触发**(造 data-access fault 的固件成本高)。opcode 路径已实测。 +4. **预先存在的两个工作区改动**(`document/milestones/06` 的 2 行、`scripts/check_test_count.sh`)会话开始就在,三轮都没碰、没带进任何 commit。 From 54553a079ed166d0a7487e963391ff814c46ddaf Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 15:46:40 +0800 Subject: [PATCH 10/14] fix(install): install generated autogen/arch_details.hpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release(v0.2.0) commit installed only include/*.hpp, but autogen/arch_details.hpp is a configure_file output in the binary dir and a PUBLIC include of the library — so an installed micro_forge couldn't actually be linked against. Add a dedicated FILES rule to install it to ${CMAKE_INSTALL_INCLUDEDIR}/autogen. Verified: cmake --install --prefix /tmp/mf-install2 now deploys include/autogen/arch_details.hpp (110 files total, no .in template leaked). --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7ca72f..8ea8f4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,11 @@ install(TARGETS micro-forge RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.hpp") +# Generated header (configure_file output in the binary dir, not under +# include/) — needed so an installed micro_forge can actually be linked +# against, since autogen/arch_details.hpp is a PUBLIC include of the library. +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/autogen/arch_details.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/autogen) if(MICRO_FORGE_GUI) install(TARGETS micro-forge-gui RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) From 2b3473753fa1faef1c66af4a84172aafaded3c05 Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 16:02:07 +0800 Subject: [PATCH 11/14] feat: add docs --- document/milestones/06-progress-assessment-and-replan.md | 2 ++ scripts/check_test_count.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/document/milestones/06-progress-assessment-and-replan.md b/document/milestones/06-progress-assessment-and-replan.md index 6df70cc..f6aff3f 100644 --- a/document/milestones/06-progress-assessment-and-replan.md +++ b/document/milestones/06-progress-assessment-and-replan.md @@ -4,6 +4,8 @@ > 阶段: v0.1.0 → v1.0.0(对 [00-v1-roadmap](00-v1-roadmap.md) 的实测校准) > 状态: 待评审 > 依赖: 当前 main 分支代码实测(217/217 测试通过)、01–05 各阶段目标文档 +> +> ⚠️ **2026-07-07 校准**:本文档为 6-19 快照(217 测试、CLI 0%、整体估 35-40%)。今日实测 **355/355 ctest 绿**(353 产品 + 2 meta)、CLI/snapshot/introspection 全齐、Qt6 GUI(milestone 04)done、Thumb-2 全覆盖 + QEMU 差分 oracle 落地、整体向 v1 约 **65-70%**。下方各里程碑完成度为 6-19 状态,已显著过期;决策请以代码 + `git log` + 内部 `document/ai/PLAN.md`(实时批表)为准。 --- diff --git a/scripts/check_test_count.sh b/scripts/check_test_count.sh index fec45fb..a7e4315 100755 --- a/scripts/check_test_count.sh +++ b/scripts/check_test_count.sh @@ -17,7 +17,7 @@ set -euo pipefail BUILD="${1:-build}" -BASELINE=321 # floor = PRODUCT test count — only ever raised, never lowered +BASELINE=353 # floor = PRODUCT test count — only ever raised, never lowered (2026-07-07: 321→353, G1-G6) if [[ ! -d "$BUILD" ]]; then echo "skip: build dir '$BUILD' not found (run cmake configure first)" From d6c46fee0c8657150071f0af047f6bc2f442ec2f Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 16:15:58 +0800 Subject: [PATCH 12/14] fix(test): guard read_file under INTROSPECTION_HELLO_ELF (CI build fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_introspection.cpp defined read_file() unconditionally but used it only inside #ifdef INTROSPECTION_HELLO_ELF. On ci.yml (gcc-14 only, no ARM toolchain) hello_firmware isn't built, so the macro is undefined and read_file became unused -> -Werror=unused-function broke the Build step. Moved the helper inside the #ifdef so it only exists when actually compiled. Not a regression from this branch (main has the same structure since G1 / notes 031) — just surfaced now that the PR ran ci.yml. Local: full build + 355 ctests green. --- test/test_introspection.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_introspection.cpp b/test/test_introspection.cpp index ca4aa7d..e413e82 100644 --- a/test/test_introspection.cpp +++ b/test/test_introspection.cpp @@ -21,13 +21,6 @@ using micro_forge::introspection::read_introspection; using micro_forge::chips::stm32f1::Stm32f103Soc; using micro_forge::cpu::CPU; -namespace { -std::vector read_file(const std::string& path) { - std::ifstream f(path, std::ios::binary); - return {std::istreambuf_iterator(f), {}}; -} -} // namespace - TEST(Introspection, FreshSocHasHaltedCpuAndNoFault) { auto soc = Stm32f103Soc::create(); ASSERT_TRUE(soc.has_value()); @@ -94,6 +87,13 @@ TEST(Introspection, FreshSocPeripheralsAreQuiescent) { } #ifdef INTROSPECTION_HELLO_ELF +namespace { +std::vector read_file(const std::string& path) { + std::ifstream f(path, std::ios::binary); + return {std::istreambuf_iterator(f), {}}; +} +} // namespace + TEST(Introspection, RunningFirmwareAdvancesCyclesAndKeepsPcInFlash) { const auto data = read_file(INTROSPECTION_HELLO_ELF); ASSERT_FALSE(data.empty()); From d259e326cd3d0e0921e7dce850c27a8a8f58974c Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 16:22:51 +0800 Subject: [PATCH 13/14] ci: install ARM toolchain on ci.yml so firmware tests + floor gate pass ci.yml had only g++-14, so find_program(arm-none-eabi-gcc) failed and hello/blink/systick firmware targets weren't built. That left test_e2e / test_cli / INTROSPECTION_HELLO_ELF unconfigured, dropping the product-test count to 344 and tripping the test_count_floor gate (baseline 353). Install gcc-arm-none-eabi + binutils-arm-none-eabi (same as cross-compile.yml) so the firmware targets build, all tests configure, and the floor gate reaches 353. Bonus: ci.yml now actually runs the firmware E2E tests instead of silently skipping them. --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9603690..6901e50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,10 +18,13 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install GCC-14 + - name: Install GCC-14 + ARM toolchain run: | sudo apt-get update - sudo apt-get install -y g++-14 + # gcc-arm-none-eabi: builds the Cortex-M3 test firmware (hello/blink/ + # systick) so test_e2e/test_cli/INTROSPECTION_HELLO_ELF configure and + # the test-count floor gate reaches its baseline on this workflow. + sudo apt-get install -y g++-14 gcc-arm-none-eabi binutils-arm-none-eabi - name: Cache GoogleTest uses: actions/cache@v4 From b4c98e3d25c1ebccaebc8a8a971c94e9bcecdcdd Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Tue, 7 Jul 2026 16:31:56 +0800 Subject: [PATCH 14/14] ci: checkout STM32CubeF1 submodule so E2E.HalUartTransmit runs on ci.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ci.yml's checkout lacked submodules: recursive, so the hal_uart firmware (needed by E2E.HalUartTransmit) wasn't built and that one product test stayed unconfigured — leaving the test-count floor one short (352 vs 353). cross-compile.yml already does this; now ci.yml matches. --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6901e50..177d65e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,11 @@ jobs: CXX: g++-14 steps: - uses: actions/checkout@v4 + with: + # STM32CubeF1 submodule is needed by hal_uart/hal_blink firmware, which + # the E2E.HalUartTransmit test loads. Without it that test doesn't + # configure and the test-count floor gate falls short by one. + submodules: recursive - name: Install GCC-14 + ARM toolchain run: |