From af0c6312b7acc13e33fd4ad738f236aee70b4b90 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Fri, 3 Jul 2026 00:10:39 +0200 Subject: [PATCH 1/2] [fiber] Fix PSPLIM triggering during context switch --- src/modm/processing/fiber/context_arm_m.cpp.in | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/modm/processing/fiber/context_arm_m.cpp.in b/src/modm/processing/fiber/context_arm_m.cpp.in index ed5e2fb7cb..55ac32a74d 100644 --- a/src/modm/processing/fiber/context_arm_m.cpp.in +++ b/src/modm/processing/fiber/context_arm_m.cpp.in @@ -188,14 +188,17 @@ modm_context_start(modm_context_t*) "orr r1, r1, #2 \n\t" // Set SPSEL %% endif "msr control, r1 \n\t" + "isb \t\n\t" %# %% if is_cm0 "ldr r1, [r0] \n\t" "mov sp, r1 \n\t" // Set PSP to ctx->sp %% elif with_psplim "ldm r0, {r1-r2} \n\t" - "msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom + "mov r3, #0 \n\t" + "msr psplim, r3 \n\t" // Disable PSPLIM "mov sp, r1 \n\t" // Set PSP to ctx->sp + "msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom %% else "ldr sp, [r0] \n\t" // Set PSP to ctx->sp %% endif @@ -240,8 +243,10 @@ modm_context_jump(modm_context_t*, modm_context_t*) "mov sp, r2 \n\t" // Restore SP from to->sp %% elif with_psplim "ldm r1, {r1-r2} \n\t" + "mov r3, #0 \n\t" + "msr psplim, r3 \n\t" // Disable PSPLIM + "mov sp, r1 \n\t" // Restore SP from to->sp "msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom - "mov sp, r1 \n\t" // Set PSP to ctx->sp %% else "ldr sp, [r1] \n\t" // Restore SP from to->sp %% endif @@ -260,6 +265,12 @@ modm_context_end(uintptr_t) { asm volatile ( +%% if with_psplim + "mov r3, #0 \n\t" + "msr psplim, r3 \n\t" // Disable PSPLIM +%# +%% endif + "mrs r1, control \n\t" %% if is_cm0 "mov r2, #2 \n\t" @@ -268,6 +279,7 @@ modm_context_end(uintptr_t) "bic r1, r1, #2 \n\t" // Unset SPSEL %% endif "msr control, r1 \n\t" + "isb \n\t" MODM_POP_CONTEXT() ); From b0f5699340586ba894144d377f3e10d914bd3c93 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Fri, 3 Jul 2026 00:10:52 +0200 Subject: [PATCH 2/2] [examples] Add PSPLIM stress test example --- examples/nucleo_h563zi/fiber/main.cpp | 99 ++++++++++++++++++++++++ examples/nucleo_h563zi/fiber/project.xml | 10 +++ 2 files changed, 109 insertions(+) create mode 100644 examples/nucleo_h563zi/fiber/main.cpp create mode 100644 examples/nucleo_h563zi/fiber/project.xml diff --git a/examples/nucleo_h563zi/fiber/main.cpp b/examples/nucleo_h563zi/fiber/main.cpp new file mode 100644 index 0000000000..4708ba3a11 --- /dev/null +++ b/examples/nucleo_h563zi/fiber/main.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include +#include +#include + +using namespace Board; +using namespace std::chrono_literals; + +namespace +{ + +constexpr uint32_t YieldGoal = 2'000'000; +volatile uint32_t yieldCounter = 0; +volatile uint32_t ringCounter = 0; + +void +yield_worker() +{ + while (true) + { + ++yieldCounter; + modm::this_fiber::yield(); + } +} + +extern modm::Fiber<512> fiberB; +extern modm::Fiber<512> fiberC; + +modm_faststack modm::Fiber<768> fiberA([]{ + ++ringCounter; + if ((ringCounter & 0x3ff) == 0) + { + const auto ring = uint32_t(ringCounter); + const auto yields = uint32_t(yieldCounter); + MODM_LOG_INFO << "ring=" << ring + << " yields=" << yields + << " A=" << fiberA.stack_usage() + << modm::endl; + } + modm::this_fiber::yield(); + fiberB.start(); +}); + +modm_faststack modm::Fiber<512> fiberB([]{ + ++ringCounter; + modm::this_fiber::yield(); + fiberC.start(); +}, modm::fiber::Start::Later); + +modm_faststack modm::Fiber<512> fiberC([]{ + ++ringCounter; + modm::this_fiber::yield(); + fiberA.start(); +}, modm::fiber::Start::Later); + +modm_faststack modm::Fiber<768> fiberYield(yield_worker); + +modm_faststack modm::Fiber<1024> fiberReporter([]{ + while (true) + { + modm::this_fiber::sleep_for(250ms); + Leds::toggle(); + const auto yields = uint32_t(yieldCounter); + const auto ring = uint32_t(ringCounter); + MODM_LOG_INFO << "report yields=" << yields + << " ring=" << ring + << " WY=" << fiberYield.stack_usage() + << " WA=" << fiberA.stack_usage() + << " WB=" << fiberB.stack_usage() + << " WC=" << fiberC.stack_usage() + << modm::endl; + } +}); + +} + +int +main() +{ + Board::initialize(); + Leds::setOutput(); + + MODM_LOG_INFO << "H563ZI fiber stress example" << modm::endl; + MODM_LOG_INFO << "Exercises repeated yield and restart handover on ARMv8-M" << modm::endl; + MODM_LOG_INFO.flush(); + + modm::fiber::Scheduler::run(modm::fiber::Scheduler::AutoWatermark); + return 0; +} \ No newline at end of file diff --git a/examples/nucleo_h563zi/fiber/project.xml b/examples/nucleo_h563zi/fiber/project.xml new file mode 100644 index 0000000000..c55784b89c --- /dev/null +++ b/examples/nucleo_h563zi/fiber/project.xml @@ -0,0 +1,10 @@ + + modm:nucleo-h563zi + + + + + modm:build:scons + modm:processing:fiber + + \ No newline at end of file