Skip to content

Commit

Permalink
[fiber] Channel, Semaphore, Mutex + Benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikssn committed Sep 10, 2020
1 parent ff95d68 commit 58784c2
Show file tree
Hide file tree
Showing 13 changed files with 717 additions and 148 deletions.
55 changes: 55 additions & 0 deletions examples/generic/fiber/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020, Erik Henriksson
*
* 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 <modm/debug/logger.hpp>
#include <modm/board.hpp>
#include <modm/processing.hpp>

using namespace Board;
using namespace std::chrono_literals;

constexpr uint32_t cycles = 1000'000;
volatile uint32_t counter = 0;

void f1() {
while (++counter < cycles) {
modm::yield();
}
}

void f2() {
while (++counter < cycles) {
asm volatile ("");
modm::yield();
}
}

modm::fiber::Stack<2048> stack1, stack2;
modm::Fiber fiber1(stack1, &f1), fiber2(stack2, &f2);


// Blue pill (M3 64MHz): Executed 1000000 in 1520841us (657530.94 yields per second)
// Feather M0 (M0+ 48MHz): Executed 1000000 in 2190108us (456598.50 yields per second)
int main( int argc, char * argv[])
{
Board::initialize();
MODM_LOG_INFO << "Starting fiber modm::yield benchmark..." << modm::endl;
MODM_LOG_INFO.flush();
const modm::PreciseTimestamp start = modm::PreciseClock::now();
modm::fiber::scheduler.start(); const auto diff = (modm::PreciseClock::now() - start);
MODM_LOG_INFO << "Benchmark done!" << modm::endl;
MODM_LOG_INFO << "Executed " << cycles << " in " << diff << " (";
MODM_LOG_INFO.printf("%.2f", cycles * 1'000'000.0 / std::chrono::microseconds(diff).count());
MODM_LOG_INFO << " yields per second)" << modm::endl;
MODM_LOG_INFO.flush();
while (1);
return 0;
}
3 changes: 3 additions & 0 deletions examples/generic/fiber/openocd.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source [find interface/stlink-v2.cfg]

set CPUTAPID 0x2ba01477
13 changes: 13 additions & 0 deletions examples/generic/fiber/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<library>
<extends>modm:blue-pill</extends>
<!-- <extends>modm:feather-m0</extends> -->
<options>
<option name="modm:build:build.path">../../../build/generic/fiber</option>
<option name="modm:build:openocd.cfg">openocd.cfg</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:processing:timer</module>
<module>modm:processing:fiber</module>
</modules>
</library>
2 changes: 1 addition & 1 deletion src/modm/platform/uart/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Instance(Module):
BooleanOption(
name="buffered",
description="",
default=True))
default=False))
module.add_option(
NumericOption(
name="buffer.tx",
Expand Down
18 changes: 18 additions & 0 deletions src/modm/processing/fiber/channel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2020, Erik Henriksson
*
* 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/.
*/
// ----------------------------------------------------------------------------

#pragma once

namespace modm {

} // namespace modm

#include "channel_impl.hpp"
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
#include <modm/debug/logger.hpp>

// Stack layout:
// r8
// r9
// r10
// r11
// r4
// r5
// r6
// r7
// r8
// r9
// r10
// r11
// LR
// PC

Expand All @@ -47,16 +47,7 @@ modm_startcontext(const modm_context &to)
"add r3, r3, #1" "\n\t" // Stay in thumb mode
"push {r3}" "\n\t" // Save instruction address to stack (to be used for PC later)

%% if "m0" in core
"push {r4-r7, lr}" "\n\t"
"mov r4, r8" "\n\t"
"mov r5, r9" "\n\t"
"mov r6, r10" "\n\t"
"mov r7, r11" "\n\t"
"push {r4-r7}" "\n\t"
%% else
"push {r4-r11, lr}" "\n\t"
%% endif

"mov r3, sp" "\n\t"
"str r3, [%[main_sp]]" "\n\t" // Store the main SP in "main_sp"
Expand All @@ -66,16 +57,7 @@ modm_startcontext(const modm_context &to)
"orr r3, r2" "\n\t"
"msr control, r3" "\n\t"

%% if "m0" in core
"pop {r4-r7}" "\n\t"
"mov r8, r4" "\n\t"
"mov r9, r5" "\n\t"
"mov r10, r6" "\n\t"
"mov r11, r7" "\n\t"
"pop {r4-r7}" "\n\t"
%% else
"pop {r4-r11}" "\n\t"
%% endif
"pop {r3}" "\n\t"
"mov lr, r3" "\n\t"

Expand All @@ -100,32 +82,13 @@ modm_jumpcontext(modm_context* from, const modm_context &to)
"add r3, r3, #1" "\n\t" // Stay in thumb mode
"push {r3}" "\n\t" // Save instruction address to stack (to be used for PC later)

%% if "m0" in core
"push {r4-r7, lr}" "\n\t"
"mov r4, r8" "\n\t"
"mov r5, r9" "\n\t"
"mov r6, r10" "\n\t"
"mov r7, r11" "\n\t"
"push {r4-r7}" "\n\t"
%% else
"push {r4-r11, lr}" "\n\t"
%% endif


"mov r3, sp" "\n\t"
"str r3, [%[from_sp]]" "\n\t" // Store the SP in "from"
"mov sp, %[to_sp]" "\n\t" // Restore SP from "to"

%% if "m0" in core
"pop {r4-r7}" "\n\t"
"mov r8, r4" "\n\t"
"mov r9, r5" "\n\t"
"mov r10, r6" "\n\t"
"mov r11, r7" "\n\t"
"pop {r4-r7}" "\n\t"
%% else
"pop {r4-r11}" "\n\t"
%% endif
"pop {r3}" "\n\t"
"mov lr, r3" "\n\t"

Expand All @@ -149,16 +112,7 @@ modm_endcontext()
"bic r1, r1, r2" "\n\t"
"msr control, r1" "\n\t"

%% if "m0" in core
"pop {r4-r7}" "\n\t"
"mov r8, r4" "\n\t"
"mov r9, r5" "\n\t"
"mov r10, r6" "\n\t"
"mov r11, r7" "\n\t"
"pop {r4-r7}" "\n\t"
%% else
"pop {r4-r11}" "\n\t"
%% endif
"pop {r3}" "\n\t"
"mov lr, r3" "\n\t"

Expand Down
137 changes: 137 additions & 0 deletions src/modm/processing/fiber/context_cortex_m0_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2020, Erik Henriksson
*
* 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 <modm/platform/device.hpp>
#include <modm/debug/logger.hpp>

// Stack layout:
// r8
// r9
// r10
// r11
// r4
// r5
// r6
// r7
// LR
// PC


modm_context
modm_makecontext(modm_stack_t* stack, std::size_t stack_size,
void (*fn)(void), void (*end)(void)) {
modm_stack_t* sp = stack + stack_size / sizeof(modm_stack_t);
*--sp = (modm_stack_t) fn; // PC
*--sp = (modm_stack_t) end; // LR
sp -= 8; // r4-r11
return {sp, stack_size};
}

void
modm_startcontext(const modm_context &to) {
modm_stack_t** main_sp = &main_context.sp;
modm_stack_t* to_sp = to.sp;
asm volatile(
"adr r3, 1f\n\t" // Load address of instruction after "pop {pc}" into r3
"add r3, r3, #1\n\t" // Stay in thumb mode
"push {r3}\n\t" // Save instruction address to stack (to be used for PC later)

"push {r4-r7, lr}\n\t"
"mov r4, r8\n\t"
"mov r5, r9\n\t"
"mov r6, r10\n\t"
"mov r7, r11\n\t"
"push {r4-r7}\n\t"

"mov r3, sp\n\t"
"str r3, [%[main_sp]]\n\t" // Store the main SP in "main_sp"
"msr psp, %[to_sp]\n\t" // Set PSP to top of stack
"mrs r3, control\n\t"
"mov r2, #0x2\n\t" // Set SPSEL
"orr r3, r2\n\t"
"msr control, r3\n\t"

"pop {r4-r7}\n\t"
"mov r8, r4\n\t"
"mov r9, r5\n\t"
"mov r10, r6\n\t"
"mov r11, r7\n\t"
"pop {r4-r7}\n\t"
"pop {r3}\n\t"
"mov lr, r3\n\t"

"pop {pc}\n\t" // Perform the jump
".align 2\n\t"
"1:\n\t"
/*outputs*/: [main_sp] "+r" (main_sp), [to_sp] "+r" (to_sp)
/*inputs*/:
/*clobbers*/: "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory");
}

void
modm_jumpcontext(modm_context* from, const modm_context &to) {
register modm_stack_t** from_sp asm("r0") = &from->sp;
register modm_stack_t* to_sp asm("r1") = to.sp;
asm volatile(
"adr r3, 1f\n\t" // Load address of instruction after "pop {pc}" into r3
"add r3, r3, #1\n\t" // Stay in thumb mode
"push {r3}\n\t" // Save instruction address to stack (to be used for PC later)

"push {r4-r7, lr}\n\t"
"mov r4, r8\n\t"
"mov r5, r9\n\t"
"mov r6, r10\n\t"
"mov r7, r11\n\t"
"push {r4-r7}\n\t"

"mov r3, sp\n\t"
"str r3, [%[from_sp]]\n\t" // Store the SP in "from"
"mov sp, %[to_sp]\n\t" // Restore SP from "to"

"pop {r4-r7}\n\t"
"mov r8, r4\n\t"
"mov r9, r5\n\t"
"mov r10, r6\n\t"
"mov r11, r7\n\t"
"pop {r4-r7}\n\t"
"pop {r3}\n\t"
"mov lr, r3\n\t"

"pop {pc}\n\t" // Perform the jump
".align 2\n\t"
"1:\n\t"
/*outputs*/: [from_sp] "+r" (from_sp), [to_sp] "+r" (to_sp)
/*inputs*/:
/*clobbers*/: "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory");
}

void
modm_endcontext() {
asm volatile(
"mrs r1, control\n\t"
"mov r2, #0x2\n\t" // Unset SPSEL
"bic r1, r1, r2\n\t"
"msr control, r1\n\t"

"pop {r4-r7}\n\t"
"mov r8, r4\n\t"
"mov r9, r5\n\t"
"mov r10, r6\n\t"
"mov r11, r7\n\t"
"pop {r4-r7}\n\t"
"pop {r3}\n\t"
"mov lr, r3\n\t"

"pop {pc}\n\t" // Perform the jump
/*outputs*/:
/*inputs*/:
/*clobbers*/: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory");
}
Loading

0 comments on commit 58784c2

Please sign in to comment.