Skip to content

Commit 7802247

Browse files
committed
WIP add stack overflow check in yield
1 parent 1463562 commit 7802247

File tree

9 files changed

+131
-98
lines changed

9 files changed

+131
-98
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#include <modm/board.hpp>
13+
#include <modm/processing.hpp>
14+
15+
using namespace Board;
16+
using namespace std::chrono_literals;
17+
18+
// modm::Fiber<> blinky([]
19+
// {
20+
// while(1)
21+
// {
22+
// Board::Leds::toggle();
23+
// modm::this_fiber::sleep_for(0.5s);
24+
// }
25+
// });
26+
27+
modm::Fiber<> bad_fiber([]
28+
{
29+
30+
MODM_LOG_INFO << "\nReboot!\nPush the button to overflow the stack!" << modm::endl;
31+
32+
while(1)
33+
{
34+
// cause stack overflow on button push
35+
if (Button::read()) asm volatile ("push {r0-r7}");
36+
modm::this_fiber::yield();
37+
}
38+
});
39+
40+
int
41+
main()
42+
{
43+
Board::initialize();
44+
Board::Leds::setOutput();
45+
46+
modm::fiber::Scheduler::run();
47+
48+
return 0;
49+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<library>
2+
<!-- <extends>modm:nucleo-u575zi-q</extends> -->
3+
<extends>modm:nucleo-g071rb</extends>
4+
<options>
5+
<option name="modm:build:build.path">../../../build/generic/fiber_overflow</option>
6+
</options>
7+
<modules>
8+
<module>modm:build:scons</module>
9+
<module>modm:processing:fiber</module>
10+
</modules>
11+
</library>

examples/nucleo_u575zi-q/fiber_overflow/project.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/modm/processing/fiber/context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ modm_context_reset(modm_context_t *ctx);
6464
* Switches control from the main context to the fiber context. This initializes
6565
* the hardware and then jumps from the caller context into the `to` fiber.
6666
*/
67-
void
67+
uintptr_t
6868
modm_context_start(modm_context_t *to);
6969

7070
/**
@@ -80,7 +80,7 @@ modm_context_jump(modm_context_t *from, modm_context_t *to) asm("modm_context_ju
8080
* `modm_context_start()` function.
8181
*/
8282
void modm_noreturn
83-
modm_context_end();
83+
modm_context_end(uintptr_t retval);
8484

8585
/**
8686
* Zeros the register file and watermarks the rest of the stack.

src/modm/processing/fiber/context_arm_m.cpp.in

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ modm_context_stack_usage(const modm_context_t *ctx)
142142
bool
143143
modm_context_stack_overflow(const modm_context_t *ctx)
144144
{
145-
return *ctx->bottom != StackWatermark;
145+
return ctx->sp >= ctx->bottom and *ctx->bottom != StackWatermark;
146146
}
147147

148148
#define MODM_PUSH_CONTEXT() \
@@ -173,7 +173,7 @@ modm_context_stack_overflow(const modm_context_t *ctx)
173173
"pop {r4-r11, pc} \n\t"
174174
%% endif
175175
%#
176-
void modm_naked
176+
uintptr_t modm_naked
177177
modm_context_start(modm_context_t*)
178178
{
179179
asm volatile
@@ -211,41 +211,57 @@ modm_context_jump(modm_context_t*, modm_context_t*)
211211
(
212212
MODM_PUSH_CONTEXT()
213213
%#
214+
%% if not with_psplim
215+
"ldr r3, [r0, #4] \n\t" // Load from->bottom
216+
%% endif
214217
%% if is_cm0
215-
"mov r2, sp \n\t"
216-
"str r2, [r0] \n\t" // Store the SP in from->sp
218+
"mov r2, sp \n\t"
219+
"str r2, [r0] \n\t" // Store the SP in from->sp
220+
%#
221+
"cmp r2, r3 \n\t" // Compare SP to from->bottom
217222
%% else
218-
"str sp, [r0] \n\t" // Store the SP in from->sp
223+
"str sp, [r0] \n\t" // Store the SP in from->sp
224+
%% if not with_psplim
225+
%#
226+
"cmp sp, r3 \n\t" // Compare SP to from->bottom
227+
%% endif
228+
%% endif
229+
%% if not with_psplim
230+
"ble modm_context_end \n\t" // If SP <= bottom, stack overflow
231+
"ldr r3, [r3] \n\t" // Load stack bottom
232+
"ldr r2, =0xf00dcafe \n\t" // Load StackWatermark value
233+
"cmp r2, r3 \n\t" // Check if stack watermark is still at the bottom
234+
"bne modm_context_end \n\t" // If not, stack overflow
219235
%% endif
220236
%#
221237
%% if is_cm0
222-
"ldr r2, [r1] \n\t"
223-
"mov sp, r2 \n\t" // Restore SP from to->sp
238+
"ldr r2, [r1] \n\t"
239+
"mov sp, r2 \n\t" // Restore SP from to->sp
224240
%% elif with_psplim
225-
"ldm r1, {r1-r2} \n\t"
226-
"msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom
227-
"mov sp, r1 \n\t" // Set PSP to ctx->sp
241+
"ldm r1, {r1-r2} \n\t"
242+
"msr psplim, r2 \n\t" // Set PSPLIM to ctx->bottom
243+
"mov sp, r1 \n\t" // Set PSP to ctx->sp
228244
%% else
229-
"ldr sp, [r1] \n\t" // Restore SP from to->sp
245+
"ldr sp, [r1] \n\t" // Restore SP from to->sp
230246
%% endif
231247
%#
232248
MODM_POP_CONTEXT()
233249
);
234250
}
235251

236252
void modm_naked
237-
modm_context_end()
253+
modm_context_end(uintptr_t)
238254
{
239255
asm volatile
240256
(
241-
"mrs r0, control \n\t"
257+
"mrs r1, control \n\t"
242258
%% if is_cm0
243-
"mov r1, #2 \n\t"
244-
"bic r0, r0, r1 \n\t" // Unset SPSEL
259+
"mov r2, #2 \n\t"
260+
"bic r1, r1, r2 \n\t" // Unset SPSEL
245261
%% else
246-
"bic r0, r0, #2 \n\t" // Unset SPSEL
262+
"bic r1, r1, #2 \n\t" // Unset SPSEL
247263
%% endif
248-
"msr control, r0 \n\t"
264+
"msr control, r1 \n\t"
249265

250266
MODM_POP_CONTEXT()
251267
);

src/modm/processing/fiber/module.lb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def is_enabled(env):
2121
not env.has_module(":processing:protothread")
2222

2323
def prepare(module, options):
24-
module.depends(":architecture:clock", ":architecture:atomic")
24+
module.depends(":architecture:clock", ":architecture:atomic", ":architecture:assert")
2525

2626
module.add_query(
2727
EnvironmentQuery(name="__enabled", factory=is_enabled))
@@ -56,7 +56,7 @@ def build(env):
5656

5757
if core.startswith("cortex-m"):
5858
env.substitutions["stack_minimum"] = (2 + 9 + (16 if with_fpu else 0)) * 4
59-
env.substitutions["default_stack_size"] = 512
59+
env.substitutions["default_stack_size"] = 1024
6060
env.template("context_arm_m.cpp.in")
6161

6262
elif core.startswith("avr"):
@@ -77,7 +77,7 @@ def build(env):
7777
env.copy("context.h")
7878
env.template("stack.hpp.in")
7979
env.template("scheduler.hpp.in")
80-
env.copy("scheduler.cpp")
80+
env.template("scheduler.cpp.in")
8181
env.copy("task.hpp")
8282
env.copy("task_impl.hpp")
8383
env.copy("functions.hpp")

src/modm/processing/fiber/scheduler.cpp

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, Niklas Hauser
2+
* Copyright (c) 2023, Niklas Hauser
33
*
44
* This file is part of the modm project.
55
*
@@ -9,34 +9,27 @@
99
*/
1010
// ----------------------------------------------------------------------------
1111

12-
#include <modm/board.hpp>
13-
#include <modm/processing.hpp>
12+
#include "scheduler.hpp"
1413

15-
using namespace Board;
16-
using namespace std::chrono_literals;
17-
18-
modm::Fiber<> blinky([]
14+
/// @cond
15+
namespace modm::this_fiber
1916
{
20-
while(1)
21-
{
22-
Board::LedBlue::toggle();
23-
modm::this_fiber::sleep_for(0.5s);
24-
}
25-
});
2617

27-
modm::Fiber<> bad_fiber([]
18+
void
19+
yield()
2820
{
21+
modm::fiber::Scheduler::instance().yield();
22+
}
2923

30-
MODM_LOG_INFO << "\nReboot!\nPush the button to overflow the stack!" << modm::endl;
24+
modm::fiber::id
25+
get_id()
26+
{
27+
return modm::fiber::Scheduler::instance().get_id();
28+
}
3129

32-
while(1)
33-
{
34-
// cause stack overflow on button push
35-
if (Button::read()) asm volatile ("push {r0-r7}");
36-
modm::this_fiber::yield();
37-
}
38-
});
30+
} // namespace modm::this_fiber
3931

32+
%% if with_psplim
4033
// On fiber stack overflow this handler will be called
4134
extern "C" void
4235
UsageFault_Handler()
@@ -51,15 +44,6 @@ UsageFault_Handler()
5144
}
5245
else HardFault_Handler();
5346
}
47+
%% endif
5448

55-
int
56-
main()
57-
{
58-
Board::initialize();
59-
// Enable the UsageFault handler
60-
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
61-
62-
modm::fiber::Scheduler::run();
63-
64-
return 0;
65-
}
49+
/// @endcond

src/modm/processing/fiber/scheduler.hpp.in

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define MODM_FIBER_SCHEDULER_HPP
1616

1717
#include "task.hpp"
18+
#include <modm/architecture/interface/assert.hpp>
1819
%% if multicore
1920
#include <modm/platform/core/multicore.hpp>
2021
%% endif
@@ -109,7 +110,13 @@ protected:
109110
{
110111
if (current == nullptr) return;
111112
Task* next = current->next;
112-
if (next == current) return;
113+
if (next == current) {
114+
%% if not with_psplim
115+
if (modm_context_stack_overflow(&current->ctx))
116+
modm_context_end((uintptr_t) current);
117+
%% endif
118+
return;
119+
}
113120
last = current;
114121
jump(*next);
115122
}
@@ -123,7 +130,7 @@ protected:
123130
if (empty())
124131
{
125132
current = nullptr;
126-
modm_context_end();
133+
modm_context_end(0);
127134
}
128135
jump(*next);
129136
__builtin_unreachable();
@@ -147,7 +154,14 @@ protected:
147154
{
148155
if (empty()) return false;
149156
current = last->next;
157+
%% if with_psplim
158+
// Enable the UsageFault handler
159+
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
150160
modm_context_start(&current->ctx);
161+
%% else
162+
const auto overflow = (Task *) modm_context_start(&current->ctx);
163+
modm_assert(not overflow, "fbr.stkof", "Fiber stack overflow", overflow);
164+
%% endif
151165
return true;
152166
}
153167

0 commit comments

Comments
 (0)