Skip to content

Commit

Permalink
[examples] WIP Replace Protothreads with Fibers
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Nov 23, 2024
1 parent b4e125b commit 0392735
Show file tree
Hide file tree
Showing 73 changed files with 846 additions and 1,283 deletions.
100 changes: 44 additions & 56 deletions examples/arduino_nano/color/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,78 +15,66 @@

using namespace modm::platform;

class Sensorthread : public modm::pt::Protothread
modm::Fiber fiber_blink([]
{
private:
modm::ShortTimeout timeout;

modm::tcs3472::Data data;
modm::Tcs3472<I2cMaster> sensor{data};
using TCS3472_INT = Board::D2;

public:
bool
update()
LedD13::setOutput();
while (true)
{
PT_BEGIN();
LedD13::toggle();
modm::this_fiber::sleep_for(0.5s);
}
});

TCS3472_INT::setInput(Gpio::InputType::PullUp);
modm::tcs3472::Data data;
modm::Tcs3472<I2cMaster> sensor{data};
using TCS3472_INT = Board::D2;
modm::Fiber fiber_sensor([]
{
TCS3472_INT::setInput(Gpio::InputType::PullUp);

MODM_LOG_INFO << "Ping TCS34725" << modm::endl;
// ping the device until it responds
while (true)
{
// we wait until the task started
if (PT_CALL(sensor.ping())) { break; }
// otherwise, try again in 100ms
timeout.restart(100ms);
PT_WAIT_UNTIL(timeout.isExpired());
}
MODM_LOG_INFO << "Ping TCS34725" << modm::endl;
// ping the device until it responds
while (true)
{
// we wait until the task started
if (sensor.ping()) break;
// otherwise, try again in 100ms
modm::this_fiber::sleep_for(100ms);
}

MODM_LOG_INFO << "TCS34725 responded" << modm::endl;
MODM_LOG_INFO << "TCS34725 responded" << modm::endl;

PT_CALL(sensor.initialize(sensor.Enable_InterruptMode_Waittime));
PT_CALL(sensor.configure(modm::tcs3472::Gain::X16, modm::tcs3472::IntegrationTime::MSEC_2_4));
PT_CALL(sensor.setInterruptPersistenceFilter(modm::tcs3472::InterruptPersistence::CNT_20));
// Setup WaitTime to further slow down samplerate
PT_CALL(sensor.setWaitTime(modm::tcs3472::WaitTime::MSEC_2_4));
sensor.initialize(sensor.Enable_InterruptMode_Waittime);
sensor.configure(modm::tcs3472::Gain::X16, modm::tcs3472::IntegrationTime::MSEC_2_4);
sensor.setInterruptPersistenceFilter(modm::tcs3472::InterruptPersistence::CNT_20);
// Setup WaitTime to further slow down samplerate
sensor.setWaitTime(modm::tcs3472::WaitTime::MSEC_2_4);

// Dummy read required
PT_CALL(sensor.readColor());
// Fetch one sample ...
PT_CALL(sensor.readColor());
// ...and set the high threshold 20% above current clear
PT_CALL(sensor.setInterruptHighThreshold(data.getClear() * 1.2));
// Dummy read required
sensor.readColor();
// Fetch one sample ...
sensor.readColor();
// ...and set the high threshold 20% above current clear
sensor.setInterruptHighThreshold(data.getClear() * 1.2);

while (true)
while (true)
{
sensor.reloadInterrupt();
modm::this_fiber::poll([]{ return not TCS3472_INT::read(); });
if (sensor.readColor())
{
PT_CALL(sensor.reloadInterrupt());
PT_WAIT_UNTIL(TCS3472_INT::read() == false);
if (PT_CALL(sensor.readColor()))
{
const auto rgb = data.getColor();
MODM_LOG_INFO << "RGB: " << rgb << "\tHSV: " << modm::color::Hsv(rgb) << modm::endl;
}
const auto rgb = data.getColor();
MODM_LOG_INFO << "RGB: " << rgb << "\tHSV: " << modm::color::Hsv(rgb) << modm::endl;
}

PT_END();
}
};

Sensorthread sensorthread;
});

int
main()
{
Board::initialize();
I2cMaster::initialize<Board::SystemClock, 100_kHz>();

LedD13::setOutput();
modm::ShortPeriodicTimer heartbeat(500ms);

while (true)
{
sensorthread.update();
if (heartbeat.execute()) Board::LedD13::toggle();
}
modm::fiber::Scheduler::run();
return 0;
}
3 changes: 1 addition & 2 deletions examples/arduino_nano/color/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:processing:protothread</module>
<module>modm:processing:timer</module>
<module>modm:processing:fiber</module>
<module>modm:platform:i2c</module>
<module>modm:driver:tcs3472</module>
</modules>
Expand Down
101 changes: 37 additions & 64 deletions examples/avr/fiber/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2020, Erik Henriksson
* Copyright (c) 2010-2011, Fabian Greif
* Copyright (c) 2012-2013, 2015-2017, Niklas Hauser
* Copyright (c) 2014, Sascha Schade
*
* This file is part of the modm project.
*
Expand All @@ -9,86 +11,57 @@
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/debug/logger.hpp>
#include <modm/platform.hpp>
#include <modm/architecture/interface/interrupt.hpp>
#include <modm/processing.hpp>

using namespace Board;
using namespace modm::platform;
using namespace std::chrono_literals;

constexpr uint32_t cycles = 100'000;
volatile uint32_t f1counter = 0, f2counter = 0;
uint32_t total_counter=0;
using LedGreen = GpioOutputB0;
using LedRed = GpioOutputB1;

void
fiber_function1()
modm::Fiber fiber_green([]
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f1counter < cycles) { modm::this_fiber::yield(); total_counter++; }
}

void
fiber_function2(uint32_t cyc)
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f2counter < cyc) { modm::this_fiber::yield(); total_counter++; }
}
LedGreen::setOutput();
LedGreen::set();

struct Test
{
void
fiber_function3()
while (true)
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f3counter < cycles) { modm::this_fiber::yield(); total_counter++; }
LedGreen::set();
modm::this_fiber::sleep_for(100ms);

LedGreen::reset();
modm::this_fiber::sleep_for(600ms);
}
});

modm::Fiber fiber_red([]
{
LedRed::setOutput();
LedRed::set();

void
fiber_function4(uint32_t cyc)
while (true)
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f4counter < cyc) { modm::this_fiber::yield(); total_counter++; }
}
LedRed::set();
modm::this_fiber::sleep_for(200ms);

LedRed::reset();
modm::this_fiber::sleep_for(300ms);

volatile uint32_t f3counter{0};
volatile uint32_t f4counter{0};
} test;
LedRed::set();
modm::this_fiber::sleep_for(200ms);

modm::Fiber<> fiber1(fiber_function1);
modm::Fiber<> fiber2(+[](){ fiber_function2(cycles); });
modm::Fiber<> fiber3(+[](){ test.fiber_function3(); });
modm::Fiber<> fiber4([cyc=uint32_t(cycles)]() mutable { cyc++; test.fiber_function4(cyc); });
LedRed::reset();
modm::this_fiber::sleep_for(1s);
}
});

// ATmega2560@16MHz: 239996 yields in 2492668us, 96280 yields per second, 10386ns per yield
int
main()
{
Board::initialize();
Board::LedD13::setOutput();
MODM_LOG_INFO << "Starting fiber modm::yield benchmark..." << modm::endl;
MODM_LOG_INFO.flush();

fiber1.stack_watermark();
fiber2.stack_watermark();
fiber3.stack_watermark();
fiber4.stack_watermark();
SystemClock::enable();
enableInterrupts();

const modm::PreciseTimestamp start = modm::PreciseClock::now();
modm::fiber::Scheduler::run();
const auto diff = (modm::PreciseClock::now() - start);

MODM_LOG_INFO << "Benchmark done!" << modm::endl;
MODM_LOG_INFO << "Executed " << total_counter << " yields in " << diff << modm::endl;
MODM_LOG_INFO << uint32_t((total_counter * 1'000'000ull) / std::chrono::microseconds(diff).count());
MODM_LOG_INFO << " yields per second, ";
MODM_LOG_INFO << uint32_t(std::chrono::nanoseconds(diff).count() / total_counter);
MODM_LOG_INFO << "ns per yield" << modm::endl;

MODM_LOG_INFO << "Stack usage 1 = " << fiber1.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 2 = " << fiber2.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 3 = " << fiber3.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 4 = " << fiber4.stack_usage() << modm::endl;

while(1) ;
return 0;
}
10 changes: 6 additions & 4 deletions examples/avr/fiber/project.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<library>
<extends>modm:mega-2560-pro</extends>
<!-- <extends>modm:arduino-nano</extends> -->
<options>
<option name="modm:target">atmega644-20au</option>
<option name="modm:platform:core:f_cpu">14.7456M</option>
<option name="modm:build:build.path">../../../build/avr/fiber</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:processing:timer</module>
<module>modm:platform:core</module>
<module>modm:platform:clock</module>
<module>modm:platform:gpio</module>
<module>modm:processing:fiber</module>
<module>modm:build:scons</module>
</modules>
</library>
94 changes: 94 additions & 0 deletions examples/avr/fiber_benchmark/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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/board.hpp>
#include <modm/debug/logger.hpp>
#include <modm/processing.hpp>

using namespace Board;
using namespace std::chrono_literals;

constexpr uint32_t cycles = 100'000;
volatile uint32_t f1counter = 0, f2counter = 0;
uint32_t total_counter=0;

void
fiber_function1()
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f1counter < cycles) { modm::this_fiber::yield(); total_counter++; }
}

void
fiber_function2(uint32_t cyc)
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f2counter < cyc) { modm::this_fiber::yield(); total_counter++; }
}

struct Test
{
void
fiber_function3()
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f3counter < cycles) { modm::this_fiber::yield(); total_counter++; }
}

void
fiber_function4(uint32_t cyc)
{
MODM_LOG_INFO << MODM_FILE_INFO << modm::endl;
while (++f4counter < cyc) { modm::this_fiber::yield(); total_counter++; }
}

volatile uint32_t f3counter{0};
volatile uint32_t f4counter{0};
} test;

modm::Fiber<> fiber1(fiber_function1);
modm::Fiber<> fiber2(+[](){ fiber_function2(cycles); });
modm::Fiber<> fiber3(+[](){ test.fiber_function3(); });
modm::Fiber<> fiber4([cyc=uint32_t(cycles)]() mutable { cyc++; test.fiber_function4(cyc); });

// ATmega2560@16MHz: 239996 yields in 2492668us, 96280 yields per second, 10386ns per yield
int
main()
{
Board::initialize();
Board::LedD13::setOutput();
MODM_LOG_INFO << "Starting fiber modm::yield benchmark..." << modm::endl;
MODM_LOG_INFO.flush();

fiber1.stack_watermark();
fiber2.stack_watermark();
fiber3.stack_watermark();
fiber4.stack_watermark();

const modm::PreciseTimestamp start = modm::PreciseClock::now();
modm::fiber::Scheduler::run();
const auto diff = (modm::PreciseClock::now() - start);

MODM_LOG_INFO << "Benchmark done!" << modm::endl;
MODM_LOG_INFO << "Executed " << total_counter << " yields in " << diff << modm::endl;
MODM_LOG_INFO << uint32_t((total_counter * 1'000'000ull) / std::chrono::microseconds(diff).count());
MODM_LOG_INFO << " yields per second, ";
MODM_LOG_INFO << uint32_t(std::chrono::nanoseconds(diff).count() / total_counter);
MODM_LOG_INFO << "ns per yield" << modm::endl;

MODM_LOG_INFO << "Stack usage 1 = " << fiber1.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 2 = " << fiber2.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 3 = " << fiber3.stack_usage() << modm::endl;
MODM_LOG_INFO << "Stack usage 4 = " << fiber4.stack_usage() << modm::endl;

while(1) ;
return 0;
}
12 changes: 12 additions & 0 deletions examples/avr/fiber_benchmark/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<library>
<extends>modm:mega-2560-pro</extends>
<!-- <extends>modm:arduino-nano</extends> -->
<options>
<option name="modm:build:build.path">../../../build/avr/fiber_benchmark</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:processing:timer</module>
<module>modm:processing:fiber</module>
</modules>
</library>
Loading

0 comments on commit 0392735

Please sign in to comment.