Skip to content

Commit d4908da

Browse files
committed
WIP add stack overflow check in yield
1 parent a90537c commit d4908da

File tree

20 files changed

+375
-294
lines changed

20 files changed

+375
-294
lines changed

examples/avr/fiber/main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ main()
6868
MODM_LOG_INFO << "Starting fiber modm::yield benchmark..." << modm::endl;
6969
MODM_LOG_INFO.flush();
7070

71-
fiber1.watermark_stack();
72-
fiber2.watermark_stack();
73-
fiber3.watermark_stack();
74-
fiber4.watermark_stack();
71+
fiber1.stack_watermark();
72+
fiber2.stack_watermark();
73+
fiber3.stack_watermark();
74+
fiber4.stack_watermark();
7575

7676
const modm::PreciseTimestamp start = modm::PreciseClock::now();
7777
modm::fiber::Scheduler::run();

examples/generic/fiber/main.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ main()
9090
MODM_LOG_INFO << "Starting fiber modm::yield benchmark..." << modm::endl;
9191
MODM_LOG_INFO.flush();
9292

93-
fiber_y1.watermark_stack();
94-
fiber_y2.watermark_stack();
93+
fiber_y1.stack_watermark();
94+
fiber_y2.stack_watermark();
9595
// fiber_y1, fiber_y2 were autostarted
9696
{
9797
modm::atomic::Lock l;
@@ -103,10 +103,10 @@ main()
103103
MODM_LOG_INFO.flush();
104104

105105
// the rest is manually started
106-
fiber1.start(); fiber1.watermark_stack();
107-
fiber2.start(); fiber2.watermark_stack();
108-
fiber3.start(); fiber3.watermark_stack();
109-
fiber4.start(); fiber4.watermark_stack();
106+
fiber1.start(); fiber1.stack_watermark();
107+
fiber2.start(); fiber2.stack_watermark();
108+
fiber3.start(); fiber3.stack_watermark();
109+
fiber4.start(); fiber4.stack_watermark();
110110
const modm::PreciseTimestamp start = modm::PreciseClock::now();
111111
modm::fiber::Scheduler::run();
112112
const auto diff = (modm::PreciseClock::now() - start);
@@ -125,8 +125,8 @@ main()
125125
MODM_LOG_INFO << "F3 stack usage = " << fiber3.stack_usage() << modm::endl;
126126
MODM_LOG_INFO << "F4 stack usage = " << fiber4.stack_usage() << modm::endl;
127127

128-
fiber_ping.watermark_stack();
129-
fiber_pong.watermark_stack();
128+
fiber_ping.stack_watermark();
129+
fiber_pong.stack_watermark();
130130
fiber_ping.start();
131131
modm::fiber::Scheduler::run();
132132

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
19+
bool overflow{false};
20+
21+
modm::Fiber<> bad_fiber([]
22+
{
23+
while(1)
24+
{
25+
#ifdef __AVR__
26+
if (overflow) asm volatile ("push r1");
27+
#else
28+
if (overflow) asm volatile ("push {r0-r7}");
29+
#endif
30+
modm::this_fiber::yield();
31+
}
32+
});
33+
34+
modm::Fiber<> blinky([]
35+
{
36+
while(1)
37+
{
38+
Board::Leds::toggle();
39+
modm::this_fiber::sleep_for(0.5s);
40+
char c;
41+
modm::log::info.get(c);
42+
if (c == 'o') overflow = true;
43+
}
44+
});
45+
46+
int
47+
main()
48+
{
49+
Board::initialize();
50+
Board::Leds::setOutput();
51+
MODM_LOG_INFO << "\nReboot!\nSend 'o' to overflow the stack!" << modm::endl;
52+
modm::delay(1s);
53+
54+
modm::fiber::Scheduler::run();
55+
56+
return 0;
57+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<library>
2+
<!-- <extends>modm:nucleo-u575zi-q</extends> -->
3+
<!-- <extends>modm:nucleo-g071rb</extends> -->
4+
<!-- <extends>modm:nucleo-l476rg</extends> -->
5+
<extends>modm:mega-2560-pro</extends>
6+
<!-- <extends>modm:arduino-uno</extends> -->
7+
<options>
8+
<option name="modm:build:build.path">../../../build/generic/fiber_overflow</option>
9+
</options>
10+
<modules>
11+
<module>modm:build:scons</module>
12+
<module>modm:processing:fiber</module>
13+
</modules>
14+
</library>

examples/nucleo_g071rb/amnb_fiber/main.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,13 @@ main()
152152
USART4->CR3 = USART_CR3_HDSEL;
153153
USART4->CR1 |= USART_CR1_UE;
154154

155-
fiberNode1t.watermark_stack();
156-
fiberNode1r.watermark_stack();
157-
fiberNode2t.watermark_stack();
158-
fiberNode2r.watermark_stack();
159-
fiberNode3t.watermark_stack();
160-
fiberNode3r.watermark_stack();
161-
thread.watermark_stack();
155+
fiberNode1t.stack_watermark();
156+
fiberNode1r.stack_watermark();
157+
fiberNode2t.stack_watermark();
158+
fiberNode2r.stack_watermark();
159+
fiberNode3t.stack_watermark();
160+
fiberNode3r.stack_watermark();
161+
thread.stack_watermark();
162162

163163
modm::fiber::Scheduler::run();
164164

examples/nucleo_u575zi-q/fiber_overflow/main.cpp

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

examples/nucleo_u575zi-q/fiber_overflow/project.xml

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

src/modm/board/mega_2560_pro/board_serial.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,33 @@ modm::log::Logger modm::log::debug(loggerDevice);
2020
modm::log::Logger modm::log::info(loggerDevice);
2121
modm::log::Logger modm::log::warning(loggerDevice);
2222
modm::log::Logger modm::log::error(loggerDevice);
23+
24+
#include <modm/architecture/interface/accessor.hpp>
25+
26+
modm_extern_c void
27+
modm_abandon(const modm::AssertionInfo &info)
28+
{
29+
MODM_LOG_ERROR << IFSS("Assertion '") << modm::accessor::asFlash(info.name) << IFSS("'");
30+
if (info.context != uintptr_t(-1)) {
31+
MODM_LOG_ERROR << IFSS(" @ ") << (void *) info.context <<
32+
IFSS(" (") << (uint32_t) info.context << IFSS(")");
33+
}
34+
#if MODM_ASSERTION_INFO_HAS_DESCRIPTION
35+
MODM_LOG_ERROR << IFSS(" failed!\n ") << modm::accessor::asFlash(info.description) << IFSS("\nAbandoning...\n");
36+
#else
37+
MODM_LOG_ERROR << IFSS(" failed!\nAbandoning...\n");
38+
#endif
39+
40+
Board::Leds::setOutput();
41+
for(int times=10; times>=0; times--)
42+
{
43+
Board::Leds::write(1);
44+
modm::delay_ms(20);
45+
Board::Leds::write(0);
46+
modm::delay_ms(180);
47+
}
48+
// Do not flush here otherwise you may deadlock due to waiting on the UART
49+
// interrupt which may never be executed when abandoning in a higher
50+
// priority Interrupt!!!
51+
// MODM_LOG_ERROR << modm::flush;
52+
}

src/modm/platform/core/cortex/assert.cpp.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <modm/debug/logger.hpp>
1717
%% elif core.startswith("avr")
1818
#include <avr/pgmspace.h>
19+
#include <avr/wdt.h>
1920
%% else
2021
#include <modm/platform/device.hpp>
2122
%% endif
@@ -77,6 +78,7 @@ modm_assert_report(_modm_assertion_info *cinfo)
7778
%% if core.startswith("cortex-m")
7879
NVIC_SystemReset();
7980
%% elif core.startswith("avr")
81+
wdt_enable(WDTO_30MS);
8082
while(1) ;
8183
%% else
8284
abort();

src/modm/processing/fiber/context.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,43 +64,39 @@ 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
/**
7171
* Pushes the context onto the `from->sp` and pops the context from the `to->sp`
7272
* to jump from one fiber to the next.
7373
*/
7474
void
75-
modm_context_jump(modm_context_t *from, modm_context_t *to) asm("modm_context_jump");
75+
modm_context_jump(modm_context_t *from, modm_context_t *to);
7676

7777
/**
7878
* Switches control from the fiber context back to the main context.
7979
* Control flow then continues in the main context by returning from the
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.
8787
* You may call this function before or after `modm_context_reset()`, however,
8888
* *NOT* while the fiber is running!
8989
*/
9090
void
91-
modm_context_watermark(modm_context_t *ctx);
91+
modm_context_stack_watermark(modm_context_t *ctx);
9292

9393
/**
9494
* Returns the stack usage by searching from the bottom of the stack for the
9595
* watermark level. You may call this function at any point after calling
96-
* `modm_context_watermark()`.
96+
* `modm_context_stack_watermark()`.
9797
*/
9898
size_t
9999
modm_context_stack_usage(const modm_context_t *ctx);
100-
101-
/// A cheap way to check if the last word of the stack was written.
102-
bool
103-
modm_context_stack_overflow(const modm_context_t *ctx);
104100
/// @}
105101

106102
#ifdef __cplusplus

0 commit comments

Comments
 (0)