11 Commits

Author SHA1 Message Date
10b7dbc19f UPD CI workflow
Some checks failed
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-bike-system) (push) Failing after 3s
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-sensor-device) (push) Failing after 2s
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-speedometer) (push) Failing after 2s
2024-11-18 09:21:22 +01:00
6867629a7a RM folder ignore for tests 2024-11-18 09:18:27 +01:00
c29ff3776e ADD answer to questions 2024-11-18 09:14:12 +01:00
9b90756e09 ADD run configurations 2024-11-18 09:14:00 +01:00
852d58b340 FIX reset task 2024-11-18 09:13:18 +01:00
818daaa9a0 FIX Static scheduling with event 2024-11-18 08:36:49 +01:00
b4d5f8028d ADD [WIP] Static scheduling with event 2024-11-17 23:09:00 +01:00
6f7ee84ea0 ADD EventQueue for static_scheduling 2024-11-17 19:13:06 +01:00
d42dcb68b1 ADD Thread sleep 2024-11-17 18:26:18 +01:00
211f362e66 ADD cpu logger 2024-11-17 18:25:48 +01:00
f079714de5 ADD bike-system super-loop with while 2024-11-17 14:20:38 +01:00
44 changed files with 604 additions and 784 deletions

1
.gitignore vendored
View File

@ -6,4 +6,3 @@ BUILD
mbed-os mbed-os
DISCO_h747i DISCO_h747i
advdembsof_library advdembsof_library
update-client

View File

@ -14,5 +14,4 @@ mbed-os/features/FEATURE_BOOTLOADER/*
mbed-os/features/frameworks/mbed-client-cli/* mbed-os/features/frameworks/mbed-client-cli/*
mbed-os/features/frameworks/COMPONENT_FPGA_CI_TEST_SHIELD/* mbed-os/features/frameworks/COMPONENT_FPGA_CI_TEST_SHIELD/*
mbed-os/platform/randlib/* mbed-os/platform/randlib/*
mbed-os/storage/kvstore/* mbed-os/storage/kvstore/*
mbed-os-bootloader/*

View File

@ -1,26 +1,24 @@
files: ^main.cpp|^static_scheduling|^static_scheduling_with_event|^TESTS files: ^main.cpp
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v4.3.0
hooks: hooks:
- id: check-yaml - id: check-yaml
args: [--allow-multiple-documents] args: [--allow-multiple-documents]
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v14.0.6" rev: 'v14.0.6'
hooks: hooks:
- id: clang-format - id: clang-format
- repo: https://github.com/cpplint/cpplint - repo: https://github.com/cpplint/cpplint
rev: "1.6.1" rev: '1.6.1'
hooks: hooks:
- id: cpplint - id: cpplint
name: cpplint - repo: local
entry: cpplint --linelength=90 --filter=-build/include_subdir,-whitespace/indent,-build/namespaces,-build/c++11 hooks:
- repo: local - id: cppcheck
hooks: name: cppcheck
- id: cppcheck require_serial: true
name: cppcheck entry: cppcheck --enable=all --suppress=missingInclude:* --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1
require_serial: true language: system
entry: cppcheck --enable=all --suppress=missingInclude --suppress=missingIncludeSystem --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1
language: system

5
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,5 @@
# Contributing to Mbed OS
Mbed OS is an open-source, device software platform for the Internet of Things. Contributions are an important part of the platform, and our goal is to make it as simple as possible to become a contributor.
To encourage productive collaboration, as well as robust, consistent and maintainable code, we have a set of guidelines for [contributing to Mbed OS](https://os.mbed.com/docs/mbed-os/latest/contributing/index.html).

165
LICENSE Normal file
View File

@ -0,0 +1,165 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.

View File

@ -82,9 +82,4 @@ We observe a light usage of 1% of CPU. The CPU is now sleeping all the time and
`Based on the program itself and on the task scheduling, explain these two behaviors. Explain also why such behaviors may be problematic.` `Based on the program itself and on the task scheduling, explain these two behaviors. Explain also why such behaviors may be problematic.`
We notice, that we miss such less event when is event driven (or not at all). But with a static scheduling the response time is still long because the reset task is call with a certain period. We notice, that we miss such less event when is event driven (or not at all). But with a static scheduling the response time is still long because the reset task is call with a certain period.
# Issues
When compile with GCC, the full loop of static scheduling is 2 to 3 ms faster than expected.
This problem doesn't occur if we compile with ARMC6.
As the acceptable delta is 2ms and the teacher test is done with GCC, we modify the delta on the test to be 3ms

View File

@ -24,16 +24,16 @@
#include <chrono> #include <chrono>
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "static_scheduling/bike_system.hpp" #include "static_scheduling/bike_system.hpp"
#include "static_scheduling_with_event/bike_system.hpp" #include "static_scheduling_with_event/bike_system.hpp"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "task_logger.hpp" #include "task_logger.hpp"
#include "unity/unity.h" #include "unity/unity.h"
#include "utest/utest.h" #include "utest/utest.h"
namespace utest { using namespace utest::v1;
namespace v1 {
// test_bike_system handler function // test_bike_system handler function
static void test_bike_system() { static void test_bike_system() {
@ -59,7 +59,7 @@ static void test_bike_system() {
800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; 800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us};
// allow for 2 msecs offset // allow for 2 msecs offset
uint64_t deltaUs = 3000; uint64_t deltaUs = 2000;
for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks;
taskIndex++) { taskIndex++) {
TEST_ASSERT_UINT64_WITHIN( TEST_ASSERT_UINT64_WITHIN(
@ -80,8 +80,7 @@ static void test_bike_system_event_queue() {
// run the bike system in a separate thread // run the bike system in a separate thread
Thread thread; Thread thread;
thread.start( thread.start(callback(&bikeSystem, &static_scheduling::BikeSystem::startWithEventQueue));
callback(&bikeSystem, &static_scheduling::BikeSystem::startWithEventQueue));
// let the bike system run for 20 secs // let the bike system run for 20 secs
ThisThread::sleep_for(20s); ThisThread::sleep_for(20s);
@ -97,7 +96,7 @@ static void test_bike_system_event_queue() {
800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; 800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us};
// allow for 2 msecs offset (with EventQueue) // allow for 2 msecs offset (with EventQueue)
uint64_t deltaUs = 3000; uint64_t deltaUs = 2000;
for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks;
taskIndex++) { taskIndex++) {
TEST_ASSERT_UINT64_WITHIN( TEST_ASSERT_UINT64_WITHIN(
@ -130,7 +129,7 @@ static void test_bike_system_with_event() {
800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; 800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us};
// allow for 2 msecs offset (with EventQueue) // allow for 2 msecs offset (with EventQueue)
uint64_t deltaUs = 3000; uint64_t deltaUs = 2000;
for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks;
taskIndex++) { taskIndex++) {
TEST_ASSERT_UINT64_WITHIN( TEST_ASSERT_UINT64_WITHIN(
@ -140,9 +139,9 @@ static void test_bike_system_with_event() {
} }
} }
static status_t greentea_setup(const size_t number_of_cases) { static utest::v1::status_t greentea_setup(const size_t number_of_cases) {
// Here, we specify the timeout (60s) and the host test (a built-in host test // Here, we specify the timeout (60s) and the host test (a built-in host test or the
// or the name of our Python file) // name of our Python file)
GREENTEA_SETUP(180, "default_auto"); GREENTEA_SETUP(180, "default_auto");
return greentea_test_setup_handler(number_of_cases); return greentea_test_setup_handler(number_of_cases);
@ -157,7 +156,4 @@ static Case cases[] = {
static Specification specification(greentea_setup, cases); static Specification specification(greentea_setup, cases);
}; // namespace v1 int main() { return !Harness::run(specification); }
}; // namespace utest
int main() { return !utest::v1::Harness::run(utest::v1::specification); }

View File

@ -29,8 +29,7 @@
#include "unity/unity.h" #include "unity/unity.h"
#include "utest/utest.h" #include "utest/utest.h"
namespace utest { using namespace utest::v1;
namespace v1 {
// test_hdc1000 test handler function // test_hdc1000 test handler function
static control_t test_sensor_device(const size_t call_count) { static control_t test_sensor_device(const size_t call_count) {
@ -54,9 +53,9 @@ static control_t test_sensor_device(const size_t call_count) {
return CaseNext; return CaseNext;
} }
static status_t greentea_setup(const size_t number_of_cases) { static utest::v1::status_t greentea_setup(const size_t number_of_cases) {
// Here, we specify the timeout (60s) and the host test (a built-in host test // Here, we specify the timeout (60s) and the host test (a built-in host test or the
// or the name of our Python file) // name of our Python file)
GREENTEA_SETUP(60, "default_auto"); GREENTEA_SETUP(60, "default_auto");
return greentea_test_setup_handler(number_of_cases); return greentea_test_setup_handler(number_of_cases);
@ -66,7 +65,5 @@ static status_t greentea_setup(const size_t number_of_cases) {
static Case cases[] = {Case("test sensor device", test_sensor_device)}; static Case cases[] = {Case("test sensor device", test_sensor_device)};
static Specification specification(greentea_setup, cases); static Specification specification(greentea_setup, cases);
}; // namespace v1
}; // namespace utest
int main() { return !utest::v1::Harness::run(utest::v1::specification); } int main() { return !Harness::run(specification); }

View File

@ -32,14 +32,13 @@
#include "unity/unity.h" #include "unity/unity.h"
#include "utest/utest.h" #include "utest/utest.h"
using namespace utest::v1;
// allow for 0.1 km/h difference // allow for 0.1 km/h difference
static constexpr float kAllowedSpeedDelta = 0.1f; static constexpr float kAllowedSpeedDelta = 0.1f;
// allow for 1m difference // allow for 1m difference
static constexpr float kAllowedDistanceDelta = 1.0f / 1000.0; static constexpr float kAllowedDistanceDelta = 1.0f / 1000.0;
namespace utest {
namespace v1 {
// function called by test handler functions for verifying the current speed // function called by test handler functions for verifying the current speed
void check_current_speed(const std::chrono::milliseconds& pedalRotationTime, void check_current_speed(const std::chrono::milliseconds& pedalRotationTime,
uint8_t traySize, uint8_t traySize,
@ -76,8 +75,7 @@ float compute_distance(const std::chrono::milliseconds& pedalRotationTime,
float trayGearRatio = static_cast<float>(traySize) / static_cast<float>(gearSize); float trayGearRatio = static_cast<float>(traySize) / static_cast<float>(gearSize);
float distancePerPedalTurn = trayGearRatio * wheelCircumference; float distancePerPedalTurn = trayGearRatio * wheelCircumference;
// distancePerPedalTurn is expressed in m, divide per 1000 for a distance in // distancePerPedalTurn is expressed in m, divide per 1000 for a distance in km
// km
return (distancePerPedalTurn * pedalRotations) / 1000.0; return (distancePerPedalTurn * pedalRotations) / 1000.0;
} }
@ -88,8 +86,7 @@ void check_distance(const std::chrono::milliseconds& pedalRotationTime,
float wheelCircumference, float wheelCircumference,
const std::chrono::milliseconds& travelTime, const std::chrono::milliseconds& travelTime,
float distance) { float distance) {
// distancePerPedalTurn is expressed in m, divide per 1000 for a distance in // distancePerPedalTurn is expressed in m, divide per 1000 for a distance in km
// km
float expectedDistance = compute_distance( float expectedDistance = compute_distance(
pedalRotationTime, traySize, gearSize, wheelCircumference, travelTime); pedalRotationTime, traySize, gearSize, wheelCircumference, travelTime);
printf(" Expected distance is %f, current distance is %f\n", printf(" Expected distance is %f, current distance is %f\n",
@ -337,9 +334,9 @@ static control_t test_reset(const size_t call_count) {
return CaseNext; return CaseNext;
} }
static status_t greentea_setup(const size_t number_of_cases) { static utest::v1::status_t greentea_setup(const size_t number_of_cases) {
// Here, we specify the timeout (60s) and the host test (a built-in host test // Here, we specify the timeout (60s) and the host test (a built-in host test or the
// or the name of our Python file) // name of our Python file)
GREENTEA_SETUP(180, "default_auto"); GREENTEA_SETUP(180, "default_auto");
return greentea_test_setup_handler(number_of_cases); return greentea_test_setup_handler(number_of_cases);
@ -353,7 +350,5 @@ static Case cases[] = {
Case("test speedometer reset", test_reset)}; Case("test speedometer reset", test_reset)};
static Specification specification(greentea_setup, cases); static Specification specification(greentea_setup, cases);
}; // namespace v1
}; // namespace utest
int main() { return !utest::v1::Harness::run(utest::v1::specification); } int main() { return !Harness::run(specification); }

View File

@ -27,8 +27,7 @@
#include "unity/unity.h" #include "unity/unity.h"
#include "utest/utest.h" #include "utest/utest.h"
namespace utest { using namespace utest::v1;
namespace v1 {
// test handler function // test handler function
static control_t always_succeed(const size_t call_count) { static control_t always_succeed(const size_t call_count) {
@ -39,9 +38,9 @@ static control_t always_succeed(const size_t call_count) {
return CaseNext; return CaseNext;
} }
static status_t greentea_setup(const size_t number_of_cases) { static utest::v1::status_t greentea_setup(const size_t number_of_cases) {
// Here, we specify the timeout (60s) and the host test (a built-in host test // Here, we specify the timeout (60s) and the host test (a built-in host test or the
// or the name of our Python file) // name of our Python file)
GREENTEA_SETUP(60, "default_auto"); GREENTEA_SETUP(60, "default_auto");
return greentea_test_setup_handler(number_of_cases); return greentea_test_setup_handler(number_of_cases);
@ -52,7 +51,4 @@ static Case cases[] = {Case("always succeed test", always_succeed)};
static Specification specification(greentea_setup, cases); static Specification specification(greentea_setup, cases);
}; // namespace v1 int main() { return !Harness::run(specification); }
}; // namespace utest
int main() { return !utest::v1::Harness::run(utest::v1::specification); }

View File

@ -24,14 +24,12 @@
* @version 0.2.0 * @version 0.2.0
***************************************************************************/ ***************************************************************************/
#include "greentea-client/test_env.h" // NOLINT #include "greentea-client/test_env.h"
#include "mbed.h" // NOLINT #include "mbed.h"
#include "unity/unity.h" // NOLINT #include "unity/unity.h"
#include "utest/utest.h" // NOLINT #include "utest/utest.h"
namespace utest {
namespace v1 {
using namespace utest::v1;
struct Test { struct Test {
Test() { Test() {
_instanceCount++; _instanceCount++;
@ -50,8 +48,7 @@ struct Test {
uint32_t Test::_instanceCount = 0; uint32_t Test::_instanceCount = 0;
/** /**
* Test that a shared pointer correctly manages the lifetime of the underlying * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer
* raw pointer
*/ */
void test_single_sharedptr_lifetime() { void test_single_sharedptr_lifetime() {
// Sanity-check value of counter // Sanity-check value of counter
@ -69,8 +66,8 @@ void test_single_sharedptr_lifetime() {
} }
/** /**
* Test that multiple instances of shared pointers correctly manage the * Test that multiple instances of shared pointers correctly manage the reference count
* reference count to release the object at the correct point * to release the object at the correct point
*/ */
void test_instance_sharing() { void test_instance_sharing() {
std::shared_ptr<Test> shared_ptr1(nullptr); std::shared_ptr<Test> shared_ptr1(nullptr);
@ -100,8 +97,8 @@ void test_instance_sharing() {
} }
/********************** /**********************
* UNIQUE PTR EXERCISE * * UNIQUE PTR EXERCISE *
**********************/ **********************/
/* /*
* Check normal lifetime on a unique_ptr * Check normal lifetime on a unique_ptr
@ -117,7 +114,7 @@ void test_single_unique_ptr_lifetime() {
TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value);
const uint32_t number = 42; const uint32_t number = 42;
p1->_value = number; p1->_value = number;
TEST_ASSERT_EQUAL(number, p1->_value); TEST_ASSERT_EQUAL(number, p1->_value);
p1.reset(); p1.reset();
@ -135,12 +132,12 @@ void test_unique_ptr_transfer() {
TEST_ASSERT_EQUAL(0, Test::_instanceCount); TEST_ASSERT_EQUAL(0, Test::_instanceCount);
{ {
// create p1 //create p1
std::unique_ptr<Test> p1 = std::make_unique<Test>(); std::unique_ptr<Test> p1 = std::make_unique<Test>();
TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value);
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
// transfer p1 to p2 //transfer p1 to p2
std::unique_ptr<Test> p2 = std::move(p1); std::unique_ptr<Test> p2 = std::move(p1);
TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value);
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
@ -148,7 +145,7 @@ void test_unique_ptr_transfer() {
p2.reset(); p2.reset();
TEST_ASSERT_EQUAL(0, Test::_instanceCount); TEST_ASSERT_EQUAL(0, Test::_instanceCount);
TEST_ASSERT(!p1); // cppcheck-suppress accessMoved TEST_ASSERT(!p1);
TEST_ASSERT(!p2); TEST_ASSERT(!p2);
} }
@ -163,13 +160,13 @@ void test_unique_ptr_release() {
TEST_ASSERT_EQUAL(0, Test::_instanceCount); TEST_ASSERT_EQUAL(0, Test::_instanceCount);
{ {
// create p1 //create p1
std::unique_ptr<Test> p1 = std::make_unique<Test>(); std::unique_ptr<Test> p1 = std::make_unique<Test>();
TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value);
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
// transfer and release p1 to p2 //transfer and release p1 to p2
Test* p2 = p1.release(); Test * p2 = p1.release();
TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value);
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
@ -195,21 +192,21 @@ void test_unique_ptr_swap() {
const uint32_t number1 = 65; const uint32_t number1 = 65;
const uint32_t number2 = 42; const uint32_t number2 = 42;
// create p1 //create p1
std::unique_ptr<Test> p1 = std::make_unique<Test>(); std::unique_ptr<Test> p1 = std::make_unique<Test>();
TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value);
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
p1->_value = number1; p1->_value = number1;
TEST_ASSERT_EQUAL(number1, p1->_value); TEST_ASSERT_EQUAL(number1, p1->_value);
// create p2 //create p2
std::unique_ptr<Test> p2 = std::make_unique<Test>(); std::unique_ptr<Test> p2 = std::make_unique<Test>();
TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value);
TEST_ASSERT_EQUAL(2, Test::_instanceCount); TEST_ASSERT_EQUAL(2, Test::_instanceCount);
p2->_value = number2; p2->_value = number2;
TEST_ASSERT_EQUAL(number2, p2->_value); TEST_ASSERT_EQUAL(number2, p2->_value);
// swap //swap
p1.swap(p2); p1.swap(p2);
TEST_ASSERT_EQUAL(number1, p2->_value); TEST_ASSERT_EQUAL(number1, p2->_value);
@ -226,13 +223,14 @@ void test_unique_ptr_swap() {
TEST_ASSERT_EQUAL(0, Test::_instanceCount); TEST_ASSERT_EQUAL(0, Test::_instanceCount);
} }
/******************* /*******************
* RAW PTR EXERCISE * * RAW PTR EXERCISE *
*******************/ *******************/
/** /**
* Test that a shared pointer correctly manages the lifetime of the underlying * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer
* raw pointer
*/ */
void test_single_raw_ptr_lifetime() { void test_single_raw_ptr_lifetime() {
// Sanity-check value of counter // Sanity-check value of counter
@ -244,12 +242,12 @@ void test_single_raw_ptr_lifetime() {
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
TEST_ASSERT_EQUAL(Test::kMagicNumber, t1._value); TEST_ASSERT_EQUAL(Test::kMagicNumber, t1._value);
Test* p1 = &t1; Test * p1 = &t1;
TEST_ASSERT_EQUAL(1, Test::_instanceCount); TEST_ASSERT_EQUAL(1, Test::_instanceCount);
TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value);
const uint32_t number1 = 42; const uint32_t number1 = 42;
p1->_value = number1; p1->_value = number1;
TEST_ASSERT_EQUAL(number1, p1->_value); TEST_ASSERT_EQUAL(number1, p1->_value);
TEST_ASSERT_EQUAL(number1, t1._value); TEST_ASSERT_EQUAL(number1, t1._value);
@ -262,9 +260,9 @@ void test_single_raw_ptr_lifetime() {
TEST_ASSERT_EQUAL(0, Test::_instanceCount); TEST_ASSERT_EQUAL(0, Test::_instanceCount);
} }
static status_t greentea_setup(const size_t number_of_cases) { static utest::v1::status_t greentea_setup(const size_t number_of_cases) {
// Here, we specify the timeout (60s) and the host test (a built-in host test // Here, we specify the timeout (60s) and the host test (a built-in host test or the
// or the name of our Python file) // name of our Python file)
GREENTEA_SETUP(60, "default_auto"); GREENTEA_SETUP(60, "default_auto");
return greentea_test_setup_handler(number_of_cases); return greentea_test_setup_handler(number_of_cases);
} }
@ -287,7 +285,4 @@ static Case cases[] = {
static Specification specification(greentea_setup, cases); static Specification specification(greentea_setup, cases);
}; // namespace v1 int main() { return !Harness::run(specification); }
}; // namespace utest
int main() { return !utest::v1::Harness::run(utest::v1::specification); }

View File

@ -110,7 +110,7 @@ void Speedometer::computeSpeed() {
// TODO : done // TODO : done
//Distance run with one pedal turn = tray size / rear gear size * circumference of the wheel //Distance run with one pedal turn = tray size / rear gear size * circumference of the wheel
constexpr float ms_in_hour = static_cast<float>(3600 * 1000); constexpr float ms_in_hour = static_cast<float>(3600 * 1000);
float pedal_rotation_per_hour = ms_in_hour / std::chrono::duration_cast<std::chrono::milliseconds>(_pedalRotationTime).count(); float pedal_rotation_per_hour = ms_in_hour / static_cast<float>(_pedalRotationTime.count());
float gear_ratio = static_cast<float>(kTraySize) / static_cast<float>(this->_gearSize); float gear_ratio = static_cast<float>(kTraySize) / static_cast<float>(this->_gearSize);
float wheel_dist_km = static_cast<float>(this->kWheelCircumference) / 1000.0; float wheel_dist_km = static_cast<float>(this->kWheelCircumference) / 1000.0;
this->_currentSpeed = gear_ratio * wheel_dist_km * pedal_rotation_per_hour; this->_currentSpeed = gear_ratio * wheel_dist_km * pedal_rotation_per_hour;
@ -141,4 +141,4 @@ void Speedometer::computeDistance() {
_lastTime = _timer.elapsed_time(); _lastTime = _timer.elapsed_time();
} }
} // namespace bike_computer } // namespace bike_computer

View File

@ -7,10 +7,8 @@
#include "mbed.h" // NOLINT #include "mbed.h" // NOLINT
#include "mbed_trace.h" #include "mbed_trace.h"
// #include "static_scheduling/bike_system.hpp" //#include "static_scheduling/bike_system.hpp"
#include "FlashIAPBlockDevice.h"
#include "static_scheduling_with_event/bike_system.hpp" #include "static_scheduling_with_event/bike_system.hpp"
#include "update-client/usb_serial_uc.hpp"
#if defined(MBED_CONF_MBED_TRACE_ENABLE) #if defined(MBED_CONF_MBED_TRACE_ENABLE)
#define TRACE_GROUP "MAIN" #define TRACE_GROUP "MAIN"
@ -21,25 +19,12 @@ int main() {
mbed_trace_init(); mbed_trace_init();
#endif #endif
tr_info("Start"); // static_scheduling::BikeSystem bikeSystem;
// bikeSystem.start();
// bikeSystem.startWithEventQueue();
FlashIAPBlockDevice flashIAPBlockDevice(MBED_ROM_START, MBED_ROM_SIZE);
update_client::USBSerialUC usbSerialUpdateClient(flashIAPBlockDevice);
update_client::UCErrorCode rc = usbSerialUpdateClient.start();
if (rc != update_client::UCErrorCode::UC_ERR_NONE) {
tr_error("Cannot initialize update client: %d", rc);
} else {
tr_info("Update client started");
}
// static_scheduling::BikeSystem bikeSystem;
static_scheduling_with_event::BikeSystem bikeSystem; static_scheduling_with_event::BikeSystem bikeSystem;
tr_debug("Starting Bike System");
// bikeSystem.startWithEventQueue();
bikeSystem.start(); bikeSystem.start();
while (true) {
}
} }
#endif // MBED_TEST_MODE #endif // MBED_TEST_MODE

Binary file not shown.

View File

@ -1,12 +0,0 @@
---
BasedOnStyle: Google
IndentWidth: 4
---
Language: Cpp
ColumnLimit: 90
AlignConsecutiveAssignments: true
DerivePointerAlignment: false
PointerAlignment: Left
BinPackArguments: false
BinPackParameters: false
IndentAccessModifiers: false

View File

@ -1,8 +0,0 @@
.build
.mbed
projectfiles
*.py*
mbed-os
BUILD
!BUILD/DISCO_H747I/GCC_ARM/mbed-os-bootloader.bin
update-client

View File

@ -1,17 +0,0 @@
mbed-os/drivers/device_key/*
mbed-os/drivers/source/usb/USBMSD.cpp
mbed-os/drivers/source/SFDP.cpp
mbed-os/connectivity/cellular/*
mbed-os/connectivity/drivers/*
mbed-os/connectivity/FEATURE_BLE/*
mbed-os/connectivity/libraries/*
mbed-os/connectivity/lorawan/*
mbed-os/connectivity/lwipstack/*
mbed-os/connectivity/nanostack/*
mbed-os/connectivity/netsocket/*
mbed-os/connectivity/nfc/*
mbed-os/features/FEATURE_BOOTLOADER/*
mbed-os/features/frameworks/mbed-client-cli/*
mbed-os/features/frameworks/COMPONENT_FPGA_CI_TEST_SHIELD/*
mbed-os/platform/randlib/*
mbed-os/storage/kvstore/*

View File

@ -1,26 +0,0 @@
files: ^main.cpp
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: check-yaml
args: [--allow-multiple-documents]
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v14.0.6"
hooks:
- id: clang-format
- repo: https://github.com/cpplint/cpplint
rev: "1.6.1"
hooks:
- id: cpplint
name: cpplint
entry: cpplint --linelength=90 --filter=-build/include_subdir,-whitespace/indent,-build/namespaces,-build/c++11
- repo: local
hooks:
- id: cppcheck
name: cppcheck
require_serial: true
entry: cppcheck --enable=all --suppress=missingInclude --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1
language: system

View File

@ -1,53 +0,0 @@
#include "mbed.h"
#include "FlashIAPBlockDevice.h"
#include "update-client/block_device_application.hpp"
#include "mbed_trace.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "BOOTLOADER"
#endif // MBED_CONF_MBED_TRACE_ENABLE
#if MBED_CONF_MBED_TRACE_ENABLE
static UnbufferedSerial g_uart(CONSOLE_TX, CONSOLE_RX);
// Function that directly outputs to an unbuffered serial port in blocking mode.
static void boot_debug(const char *s) {
size_t len = strlen(s);
g_uart.write(s, len);
g_uart.write("\r\n", 2);
}
#endif
int main() {
#if MBED_CONF_MBED_TRACE_ENABLE
mbed_trace_init();
mbed_trace_print_function_set(boot_debug);
#endif // MBED_CONF_MBED_TRACE_ENABLE
tr_debug("BikeComputer bootloader\r");
FlashIAPBlockDevice flashIAPBlockDevice(MBED_ROM_START, MBED_ROM_SIZE);
int ret = flashIAPBlockDevice.init();
if(ret == 0) {
update_client::BlockDeviceApplication app(flashIAPBlockDevice, HEADER_ADDR - MBED_ROM_START, POST_APPLICATION_ADDR - MBED_ROM_START); //MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS);//
tr_debug("Checking active application\n");
tr_debug("MBED_ROM_START : 0x%08x", MBED_ROM_START);
tr_debug("MBED_ROM_SIZE : 0x%08x", MBED_ROM_SIZE);
tr_debug("HEADER_ADDR : 0x%08x", HEADER_ADDR);
tr_debug("APPLICATION_ADDR : 0x%08x", APPLICATION_ADDR);
tr_debug("POST_APPLICATION_ADDR : 0x%08x\n", POST_APPLICATION_ADDR);
update_client::UCErrorCode ret = app.checkApplication();
if(ret == update_client::UCErrorCode::UC_ERR_NONE) {
tr_debug("Application is valid");
void *sp = *((void **) POST_APPLICATION_ADDR + 0); // NOLINT(readability/casting)
void *pc = *((void **) POST_APPLICATION_ADDR + 1); // NOLINT(readability/casting)
tr_debug("Starting application at address 0x%08x (sp 0x%08x, pc 0x%08x)", POST_APPLICATION_ADDR, (uint32_t) sp, (uint32_t) pc);
mbed_start_application(POST_APPLICATION_ADDR);
}
tr_error("Error on check of the application");
}
tr_error("Error on init flash IAP block device");
return -1;
}

View File

@ -1 +0,0 @@
https://github.com/ARMmbed/mbed-os.git#17dc3dc2e6e2817a8bd3df62f38583319f0e4fed

View File

@ -1,32 +0,0 @@
{
"macros": [
"MBED_CONF_MBED_TRACE_FEA_IPV6=0",
"MBED_BOOTLOADER_FLASH_BANK_SIZE=MBED_ROM_SIZE/2"
],
"config": {
"main-stack-size": {
"value": 4096
}
},
"target_overrides": {
"*": {
"mbed-trace.enable": false,
"platform.stdio-convert-newlines": true,
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"platform.stdio-buffered-serial": true,
"platform.all-stats-enabled": true,
"target.printf_lib":"minimal-printf",
"platform.minimal-printf-enable-floating-point": true,
"platform.minimal-printf-set-floating-point-max-decimals": 2,
"update-client.storage-address": "(MBED_BOOTLOADER_FLASH_BANK_SIZE)",
"update-client.storage-size": "(MBED_BOOTLOADER_FLASH_BANK_SIZE)",
"update-client.storage-locations": 2
},
"DISCO_H747I": {
"target.restrict_size": "0x20000",
"mbed-trace.enable": true,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG"
}
}
}

View File

@ -1,22 +0,0 @@
{
"name": "bootloader",
"target_overrides": {
"*": {
"target.header_format": [
["magic", "const", "32be", "0x5a51b3d4"],
["version", "const", "32be", "2"],
["firmwareVersion", "timestamp", "64be", null],
["firmwareSize", "size", "64be", ["application"]],
["firmwareHash", "digest", "SHA256", "application"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["campaign", "const", "64be", "0"],
["campaign", "const", "64be", "0"],
["firmwareSignatureSize", "const", "32be", "0"],
["headerCRC", "digest", "CRCITT32be", "header"]
]
}
}
}

View File

@ -1 +0,0 @@
https://github.com/SergeAyer/update-client#82fe2add70c714d9ce943f1a7dc5fda7dba75dba

View File

@ -1,8 +1,6 @@
{ {
"macros": [ "macros": [
"MBED_CONF_MBED_TRACE_FEA_IPV6=0", "MBED_CONF_MBED_TRACE_FEA_IPV6=0"
"MBED_BOOTLOADER_FLASH_BANK_SIZE=MBED_ROM_SIZE/2",
"USE_USB_SERIAL_UC=1"
], ],
"config": { "config": {
"main-stack-size": { "main-stack-size": {
@ -19,16 +17,11 @@
"platform.all-stats-enabled": true, "platform.all-stats-enabled": true,
"target.printf_lib":"minimal-printf", "target.printf_lib":"minimal-printf",
"platform.minimal-printf-enable-floating-point": true, "platform.minimal-printf-enable-floating-point": true,
"platform.minimal-printf-set-floating-point-max-decimals": 2, "platform.minimal-printf-set-floating-point-max-decimals": 2
"update-client.storage-address": "(MBED_BOOTLOADER_FLASH_BANK_SIZE)",
"update-client.storage-size": "(MBED_BOOTLOADER_FLASH_BANK_SIZE)",
"update-client.storage-locations": 2
}, },
"DISCO_H747I": { "DISCO_H747I": {
"mbed-trace.enable": true, "mbed-trace.enable": true,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG", "mbed-trace.max-level": "TRACE_LEVEL_DEBUG"
"target.bootloader_img":"./mbed-os-bootloader/BUILD/DISCO_H747I/GCC_ARM/mbed-os-bootloader.bin",
"target.header_offset": "0x20000"
} }
} }
} }

View File

@ -1,22 +0,0 @@
{
"name": "bootloader",
"target_overrides": {
"*": {
"target.header_format": [
["magic", "const", "32be", "0x5a51b3d4"],
["version", "const", "32be", "2"],
["firmwareVersion", "timestamp", "64be", null],
["firmwareSize", "size", "64be", ["application"]],
["firmwareHash", "digest", "SHA256", "application"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["hashpad", "const", "64be", "0"],
["campaign", "const", "64be", "0"],
["campaign", "const", "64be", "0"],
["firmwareSignatureSize", "const", "32be", "0"],
["headerCRC", "digest", "CRCITT32be", "header"]
]
}
}
}

View File

@ -1,83 +0,0 @@
#include "my_candidate_applications.h"
#include "mbed_trace.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "MyCandidateApplications"
#endif // MBED_CONF_MBED_TRACE_ENABLE
update_client::CandidateApplications *createCandidateApplications(
BlockDevice &blockDevice,
mbed::bd_addr_t storageAddr,
mbed::bd_size_t storageSize,
uint32_t headerSize,
uint32_t nSlots
){
tr_debug("Create my candidate application");
update_client::CandidateApplications* candidate = new bike_computer::MyCandidateApplications(blockDevice, storageAddr, storageSize, headerSize, nSlots);
return candidate;
}
namespace bike_computer {
MyCandidateApplications::MyCandidateApplications(
BlockDevice &blockDevice,
mbed::bd_addr_t storageAddr,
mbed::bd_size_t storageSize,
uint32_t headerSize,
uint32_t nSlots
) : update_client::CandidateApplications(blockDevice, storageAddr, storageSize, headerSize, nSlots) {
}
uint32_t MyCandidateApplications::getSlotForCandidate() {
tr_debug("Get slot for candidate");
uint32_t nbrOfSlots = getNbrOfSlots();
for (uint32_t slotIndex = 0; slotIndex < nbrOfSlots; slotIndex++) {
if (! getBlockDeviceApplication(slotIndex).isValid()) {
return slotIndex;
}
}
// return the slot of the oldest firmware candidates
uint32_t oldestSlotIndex = 0;
uint64_t oldestFirmwareVersion = getBlockDeviceApplication(oldestSlotIndex).getFirmwareVersion();
for (uint32_t slotIndex = 1; slotIndex < nbrOfSlots; slotIndex++) {
mbed::bd_addr_t candidateAddress = 0;
mbed::bd_size_t slotSize = 0;
getCandidateAddress(slotIndex, candidateAddress, slotSize);
tr_debug("Checking application at slot %" PRIu32 " (address 0x%" PRIx64 ", size %" PRIu64 ")",
slotIndex, candidateAddress, slotSize);
if (getBlockDeviceApplication(slotIndex).getFirmwareVersion() < oldestFirmwareVersion) {
oldestSlotIndex = slotIndex;
oldestFirmwareVersion = getBlockDeviceApplication(slotIndex).getFirmwareVersion();
}
}
return oldestSlotIndex;
}
//uint32_t MyCandidateApplications::getSlotForCandidate() {
// mbed::bd_addr_t _storageAddress = MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS;
// tr_debug("Get slot for candidate");
//
// FlashIAPBlockDevice flashIAPBlockDevice(MBED_ROM_START, MBED_ROM_SIZE);
// int ret = flashIAPBlockDevice.init();
//
// if(ret == 0){
// for (int i = 0; i < getNbrOfSlots(); i++) {
// mbed::bd_addr_t headerAddress = HEADER_ADDR - MBED_ROM_START;
// mbed::bd_addr_t applicationAddress = _storageAddress + i * getSlotSize();
// update_client::BlockDeviceApplication activeApplication(flashIAPBlockDevice, headerAddress, applicationAddress);
// update_client::UCErrorCode rc = activeApplication.checkApplication();
//
// if (update_client::UCErrorCode::UC_ERR_NONE != rc) {
// return _storageAddress + i * getSlotSize();
// }
// }
// }
// return -1;
//}
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "update-client/candidate_applications.hpp"
namespace bike_computer {
class MyCandidateApplications : public update_client::CandidateApplications {
public:
MyCandidateApplications(
BlockDevice &blockDevice,
mbed::bd_addr_t storageAddr,
mbed::bd_size_t storageSize,
uint32_t headerSize,
uint32_t nSlots
);
virtual uint32_t getSlotForCandidate() override;
};
}
update_client::CandidateApplications *createCandidateApplications(
BlockDevice &blockDevice,
mbed::bd_addr_t storageAddr,
mbed::bd_size_t storageSize,
uint32_t headerSize,
uint32_t nSlots
);

View File

@ -35,34 +35,38 @@
namespace static_scheduling { namespace static_scheduling {
static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms; static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms;
static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms; static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms;
static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms; static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 0ms; // 0 or 100ms static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 0ms; // 0 or 100ms
static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms; static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms;
static constexpr std::chrono::milliseconds kDisplayTask1Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask1Period = 1600ms;
static constexpr std::chrono::milliseconds kDisplayTask1Delay = 300ms; static constexpr std::chrono::milliseconds kDisplayTask1Delay = 300ms;
static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime = 200ms; static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime = 200ms;
static constexpr std::chrono::milliseconds kResetTaskPeriod = 800ms; static constexpr std::chrono::milliseconds kResetTaskPeriod = 800ms;
static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms; static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms;
static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kTemperatureTaskPeriod = 1600ms; static constexpr std::chrono::milliseconds kTemperatureTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kTemperatureTaskDelay = 1100ms; static constexpr std::chrono::milliseconds kTemperatureTaskDelay = 1100ms;
static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms;
static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms;
static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms;
static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms; static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kCPUTaskDelay = 0ms; static constexpr std::chrono::milliseconds kCPUTaskDelay = 0ms;
static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 0ms; static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 0ms;
BikeSystem::BikeSystem()
: _gearDevice(_timer), BikeSystem::BikeSystem() :
_pedalDevice(_timer), _gearDevice(_timer),
_resetDevice(_timer), _pedalDevice(_timer),
_speedometer(_timer), _resetDevice(_timer),
_cpuLogger(_timer) {} _speedometer(_timer),
_cpuLogger(_timer)
{
}
void BikeSystem::start() { void BikeSystem::start() {
tr_info("Starting Super-Loop without event handling"); tr_info("Starting Super-Loop without event handling");
@ -72,17 +76,19 @@ void BikeSystem::start() {
while (true) { while (true) {
auto startTime = _timer.elapsed_time(); auto startTime = _timer.elapsed_time();
gearTask(); // 100ms : 0ms -> 100ms gearTask(); // 100ms : 0ms -> 100ms
speedDistanceTask(); // 200ms : 100ms -> 300ms speedDistanceTask(); // 200ms : 100ms -> 300ms
displayTask1(); // 200ms : 300ms -> 500ms displayTask1(); // 200ms : 300ms -> 500ms
speedDistanceTask(); // 200ms : 500ms -> 700ms speedDistanceTask(); // 200ms : 500ms -> 700ms
resetTask(); // 100ms : 700ms -> 800ms resetTask(); // 100ms : 700ms -> 800ms
gearTask(); // 100ms : 800ms -> 900ms gearTask(); // 100ms : 800ms -> 900ms
speedDistanceTask(); // 200ms : 900ms -> 1100ms speedDistanceTask(); // 200ms : 900ms -> 1100ms
temperatureTask(); // 100ms : 1100ms -> 1200ms temperatureTask(); // 100ms : 1100ms -> 1200ms
displayTask2(); // 100ms : 1200ms -> 1300ms displayTask2(); // 100ms : 1200ms -> 1300ms
speedDistanceTask(); // 200ms : 1300ms -> 1500ms speedDistanceTask(); // 200ms : 1300ms -> 1500ms
resetTask(); // 100ms : 1500ms -> 1600ms resetTask(); // 100ms : 1500ms -> 1600ms
// register the time at the end of the cyclic schedule period and print the // register the time at the end of the cyclic schedule period and print the
// elapsed time for the period // elapsed time for the period
@ -91,32 +97,35 @@ void BikeSystem::start() {
std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime); std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count()); tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count());
// TODO: implement loop exit when applicable
// Done
bool fStop = false; bool fStop = false;
core_util_atomic_load(&fStop); core_util_atomic_load(&fStop);
if (fStop) { if (fStop) {
break; break;
} }
#if !defined(MBED_TEST_MODE) #if !defined(MBED_TEST_MODE)
_cpuLogger.printStats(); _cpuLogger.printStats();
#endif #endif
} }
} }
void BikeSystem::startWithEventQueue() { void BikeSystem::startWithEventQueue() {
tr_info("Starting Super-Loop with event handling"); tr_info("Starting Super-Loop with event handling");
init(); init();
EventQueue eventQueue; EventQueue eventQueue;
Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask));
gearEvent.delay(kGearTaskDelay); gearEvent.delay(kGearTaskDelay);
gearEvent.period(kGearTaskPeriod); gearEvent.period(kGearTaskPeriod);
gearEvent.post(); gearEvent.post();
Event<void()> speedDistanceEvent(&eventQueue, Event<void()> speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask));
callback(this, &BikeSystem::speedDistanceTask));
speedDistanceEvent.delay(kSpeedDistanceTaskDelay); speedDistanceEvent.delay(kSpeedDistanceTaskDelay);
speedDistanceEvent.period(kSpeedDistanceTaskPeriod); speedDistanceEvent.period(kSpeedDistanceTaskPeriod);
speedDistanceEvent.post(); speedDistanceEvent.post();
@ -131,8 +140,7 @@ void BikeSystem::startWithEventQueue() {
resetEvent.period(kResetTaskPeriod); resetEvent.period(kResetTaskPeriod);
resetEvent.post(); resetEvent.post();
Event<void()> temperatureEvent(&eventQueue, Event<void()> temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask));
callback(this, &BikeSystem::temperatureTask));
temperatureEvent.delay(kTemperatureTaskDelay); temperatureEvent.delay(kTemperatureTaskDelay);
temperatureEvent.period(kTemperatureTaskPeriod); temperatureEvent.period(kTemperatureTaskPeriod);
temperatureEvent.post(); temperatureEvent.post();
@ -142,14 +150,14 @@ void BikeSystem::startWithEventQueue() {
display2Event.period(kDisplayTask2Period); display2Event.period(kDisplayTask2Period);
display2Event.post(); display2Event.post();
#if !defined(MBED_TEST_MODE) #if !defined(MBED_TEST_MODE)
Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask));
cpuEvent.delay(kCPUTaskDelay); cpuEvent.delay(kCPUTaskDelay);
cpuEvent.period(kCPUTaskPeriod); cpuEvent.period(kCPUTaskPeriod);
cpuEvent.post(); cpuEvent.post();
#endif #endif
eventQueue.dispatch_forever(); eventQueue.dispatch_forever();
} }
void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); }
@ -187,7 +195,8 @@ void BikeSystem::gearTask() {
_currentGearSize = _gearDevice.getCurrentGearSize(); _currentGearSize = _gearDevice.getCurrentGearSize();
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime
);
} }
void BikeSystem::speedDistanceTask() { void BikeSystem::speedDistanceTask() {
@ -198,11 +207,12 @@ void BikeSystem::speedDistanceTask() {
_speedometer.setCurrentRotationTime(pedalRotationTime); _speedometer.setCurrentRotationTime(pedalRotationTime);
_speedometer.setGearSize(_currentGearSize); _speedometer.setGearSize(_currentGearSize);
// no need to protect access to data members (single threaded) // no need to protect access to data members (single threaded)
_currentSpeed = _speedometer.getCurrentSpeed(); _currentSpeed = _speedometer.getCurrentSpeed();
_traveledDistance = _speedometer.getDistance(); _traveledDistance = _speedometer.getDistance();
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime
);
} }
void BikeSystem::temperatureTask() { void BikeSystem::temperatureTask() {
@ -215,16 +225,18 @@ void BikeSystem::temperatureTask() {
tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count()); tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count());
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
// simulate task computation by waiting for the required task computation time // simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime = // std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
// std::chrono::microseconds::zero(); while (elapsedTime < // while (elapsedTime < kTemperatureTaskComputationTime) {
// kTemperatureTaskComputationTime) { // elapsedTime = _timer.elapsed_time() - taskStartTime;
// elapsedTime = _timer.elapsed_time() - taskStartTime; // }
// }
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
@ -251,16 +263,18 @@ void BikeSystem::displayTask1() {
_displayDevice.displaySpeed(_currentSpeed); _displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance); _displayDevice.displayDistance(_traveledDistance);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
// simulate task computation by waiting for the required task computation time // simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime = // std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
// std::chrono::microseconds::zero(); while (elapsedTime < // while (elapsedTime < kDisplayTask1ComputationTime) {
// kDisplayTask1ComputationTime) { // elapsedTime = _timer.elapsed_time() - taskStartTime;
// elapsedTime = _timer.elapsed_time() - taskStartTime; // }
// }
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
@ -271,20 +285,24 @@ void BikeSystem::displayTask2() {
_displayDevice.displayTemperature(_currentTemperature); _displayDevice.displayTemperature(_currentTemperature);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
// simulate task computation by waiting for the required task computation time // simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime = // std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
// std::chrono::microseconds::zero(); while (elapsedTime < // while (elapsedTime < kDisplayTask2ComputationTime) {
// kDisplayTask2ComputationTime) { // elapsedTime = _timer.elapsed_time() - taskStartTime;
// elapsedTime = _timer.elapsed_time() - taskStartTime; // }
// }
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime);
} }
void BikeSystem::cpuTask() { _cpuLogger.printStats(); } void BikeSystem::cpuTask() {
_cpuLogger.printStats();
}
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -25,9 +25,9 @@
#pragma once #pragma once
// from advembsof // from advembsof
#include "cpu_logger.hpp"
#include "display_device.hpp" #include "display_device.hpp"
#include "task_logger.hpp" #include "task_logger.hpp"
#include "cpu_logger.hpp"
// from common // from common
#include "sensor_device.hpp" #include "sensor_device.hpp"
@ -79,12 +79,12 @@ class BikeSystem {
Timer _timer; Timer _timer;
// data member that represents the device for manipulating the gear // data member that represents the device for manipulating the gear
GearDevice _gearDevice; GearDevice _gearDevice;
uint8_t _currentGear = bike_computer::kMinGear; uint8_t _currentGear = bike_computer::kMinGear;
uint8_t _currentGearSize = bike_computer::kMinGearSize; uint8_t _currentGearSize = bike_computer::kMinGearSize;
// data member that represents the device for manipulating the pedal rotation // data member that represents the device for manipulating the pedal rotation
// speed/time // speed/time
PedalDevice _pedalDevice; PedalDevice _pedalDevice;
float _currentSpeed = 0.0f; float _currentSpeed = 0.0f;
float _traveledDistance = 0.0f; float _traveledDistance = 0.0f;
// data member that represents the device used for resetting // data member that represents the device used for resetting
ResetDevice _resetDevice; ResetDevice _resetDevice;
@ -103,4 +103,4 @@ class BikeSystem {
advembsof::CPULogger _cpuLogger; advembsof::CPULogger _cpuLogger;
}; };
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -80,4 +80,4 @@ uint8_t GearDevice::getCurrentGearSize() const {
return bike_computer::kMaxGearSize - _currentGear; return bike_computer::kMaxGearSize - _currentGear;
} }
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -47,4 +47,4 @@ class GearDevice {
Timer& _timer; Timer& _timer;
}; };
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -1,25 +1,12 @@
// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**************************************************************************** /****************************************************************************
* @file pedal_device.cpp * @file pedal_device.cpp
* @author Rémi Heredero <remi@heredero.ch> * @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com> * @author Yann Sierro <yannsierro.pro@gmail.com>
* *
* @brief Pedal Device implementation (static scheduling) * @brief Pedal Device implementation (static scheduling)
* @date 2024-11-09 * @date 2024-11-09
* @version 0.1.0 * @version 0.1.0
****************************************************************************/ ****************************************************************************/
#include "pedal_device.hpp" #include "pedal_device.hpp"
@ -35,50 +22,51 @@
namespace static_scheduling { namespace static_scheduling {
static constexpr std::chrono::microseconds kTaskRunTime = 200000us; static constexpr std::chrono::microseconds kTaskRunTime = 200000us;
PedalDevice::PedalDevice(Timer& timer) : _timer(timer) {} PedalDevice::PedalDevice(Timer& timer) : _timer(timer) {}
std::chrono::milliseconds PedalDevice::getCurrentRotationTime() {
std::chrono::microseconds initialTime = _timer.elapsed_time();
std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
// we bound the change to one increment/decrement per call
bool hasChanged = false;
while (elapsedTime < kTaskRunTime) {
if (!hasChanged) {
disco::Joystick::State joystickState =
disco::Joystick::getInstance().getState();
switch (joystickState) { std::chrono::milliseconds PedalDevice::getCurrentRotationTime() {
case disco::Joystick::State::LeftPressed: // TODO
if (_pedalRotationTime < bike_computer::kMaxPedalRotationTime) { std::chrono::microseconds initialTime = _timer.elapsed_time();
decreaseRotationSpeed(); std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
hasChanged = true; // we bound the change to one increment/decrement per call
} bool hasChanged = false;
break; while (elapsedTime < kTaskRunTime) {
if (!hasChanged) {
disco::Joystick::State joystickState = disco::Joystick::getInstance().getState();
case disco::Joystick::State::DownPressed: switch (joystickState) {
if (_pedalRotationTime > bike_computer::kMinPedalRotationTime) { case disco::Joystick::State::LeftPressed:
decreaseRotationSpeed(); if (_pedalRotationTime < bike_computer::kMaxPedalRotationTime) {
hasChanged = true; decreaseRotationSpeed();
} hasChanged = true;
break; }
break;
default: case disco::Joystick::State::DownPressed:
break; if (_pedalRotationTime > bike_computer::kMinPedalRotationTime) {
} decreaseRotationSpeed();
} hasChanged = true;
elapsedTime = _timer.elapsed_time() - initialTime; }
break;
default:
break;
}
}
elapsedTime = _timer.elapsed_time() - initialTime;
}
return _pedalRotationTime;
} }
return _pedalRotationTime;
}
void PedalDevice::increaseRotationSpeed() { void PedalDevice::increaseRotationSpeed() {
_pedalRotationTime -= bike_computer::kDeltaPedalRotationTime; _pedalRotationTime -= bike_computer::kDeltaPedalRotationTime;
} }
void PedalDevice::decreaseRotationSpeed() { void PedalDevice::decreaseRotationSpeed() {
_pedalRotationTime += bike_computer::kDeltaPedalRotationTime; _pedalRotationTime += bike_computer::kDeltaPedalRotationTime;
} }
} // namespace static_scheduling }

View File

@ -51,4 +51,4 @@ class PedalDevice {
Timer& _timer; Timer& _timer;
}; };
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -1,26 +1,12 @@
// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**************************************************************************** /****************************************************************************
* @file reset_device.cpp * @file reset_device.cpp
* @author Rémi Heredero <remi@heredero.ch> * @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com> * @author Yann Sierro <yannsierro.pro@gmail.com>
* *
* @brief Reset Device implementation (static scheduling) * @brief Reset Device implementation (static scheduling)
* @date 2024-11-12 * @date 2024-11-12
* @version 0.1.0 * @version 0.1.0
****************************************************************************/ ****************************************************************************/
#include "reset_device.hpp" #include "reset_device.hpp"
@ -35,35 +21,43 @@
static constexpr uint8_t kPolarityPressed = 1; static constexpr uint8_t kPolarityPressed = 1;
#endif #endif
#if MBED_CONF_MBED_TRACE_ENABLE #if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "ResetDevice" #define TRACE_GROUP "ResetDevice"
#endif // MBED_CONF_MBED_TRACE_ENABLE #endif // MBED_CONF_MBED_TRACE_ENABLE
namespace static_scheduling { namespace static_scheduling {
static constexpr std::chrono::microseconds kTaskRunTime = 100000us; static constexpr std::chrono::microseconds kTaskRunTime = 100000us;
ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) { ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) {
_resetButton.rise(callback(this, &ResetDevice::onRise)); _resetButton.rise(callback(this, &ResetDevice::onRise));
} }
bool ResetDevice::checkReset() { bool ResetDevice::checkReset() {
std::chrono::microseconds initialTime = _timer.elapsed_time(); std::chrono::microseconds initialTime = _timer.elapsed_time();
std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero();
// we bound the change to one increment/decrement per call // we bound the change to one increment/decrement per call
bool isPressed = false; bool isPressed = false;
while (elapsedTime < kTaskRunTime) { while (elapsedTime < kTaskRunTime) {
if (!isPressed) { if(!isPressed) {
isPressed = _resetButton.read() == kPolarityPressed; isPressed = _resetButton.read() == kPolarityPressed;
} }
elapsedTime = _timer.elapsed_time() - initialTime; elapsedTime = _timer.elapsed_time() - initialTime;
}
return isPressed;
}
std::chrono::microseconds ResetDevice::getPressTime() {
return _pressTime;
} }
return isPressed; void ResetDevice::onRise() {
} _pressTime = _timer.elapsed_time();
}
std::chrono::microseconds ResetDevice::getPressTime() { return _pressTime; }
void ResetDevice::onRise() { _pressTime = _timer.elapsed_time(); }
} // namespace static_scheduling }

View File

@ -53,4 +53,4 @@ class ResetDevice {
std::chrono::microseconds _pressTime; std::chrono::microseconds _pressTime;
}; };
} // namespace static_scheduling } // namespace static_scheduling

View File

@ -35,55 +35,59 @@
namespace static_scheduling_with_event { namespace static_scheduling_with_event {
static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms; static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms;
static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms; static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms;
static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms; static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 100ms; static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 100ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms; static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms;
static constexpr std::chrono::milliseconds kDisplayTask1Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask1Period = 1600ms;
static constexpr std::chrono::milliseconds kDisplayTask1Delay = 300ms; static constexpr std::chrono::milliseconds kDisplayTask1Delay = 300ms;
static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime = 200ms; static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime = 200ms;
static constexpr std::chrono::milliseconds kResetTaskPeriod = 800ms; static constexpr std::chrono::milliseconds kResetTaskPeriod = 800ms;
static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms; static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms;
static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kTemperatureTaskPeriod = 1600ms; static constexpr std::chrono::milliseconds kTemperatureTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kTemperatureTaskDelay = 1100ms; static constexpr std::chrono::milliseconds kTemperatureTaskDelay = 1100ms;
static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms;
static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms;
static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms;
static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms; static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kCPUTaskDelay = 1200ms; static constexpr std::chrono::milliseconds kCPUTaskDelay = 1200ms;
static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 100ms; static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 100ms;
BikeSystem::BikeSystem()
: _gearDevice(), BikeSystem::BikeSystem() :
_pedalDevice(), _gearDevice(),
_resetDevice(callback(this, &BikeSystem::onReset)), _pedalDevice(),
_speedometer(_timer), _resetDevice(callback(this, &BikeSystem::onReset)),
_cpuLogger(_timer) {} _speedometer(_timer),
_cpuLogger(_timer)
{
}
void BikeSystem::start() { void BikeSystem::start() {
tr_info("Starting Super-Loop with event handling"); tr_info("Starting Super-Loop with event handling");
init(); init();
EventQueue eventQueue; EventQueue eventQueue;
Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask));
gearEvent.delay(kGearTaskDelay); gearEvent.delay(kGearTaskDelay);
gearEvent.period(kGearTaskPeriod); gearEvent.period(kGearTaskPeriod);
gearEvent.post(); gearEvent.post();
Event<void()> speedDistanceEvent(&eventQueue, Event<void()> speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask));
callback(this, &BikeSystem::speedDistanceTask));
speedDistanceEvent.delay(kSpeedDistanceTaskDelay); speedDistanceEvent.delay(kSpeedDistanceTaskDelay);
speedDistanceEvent.period(kSpeedDistanceTaskPeriod); speedDistanceEvent.period(kSpeedDistanceTaskPeriod);
speedDistanceEvent.post(); speedDistanceEvent.post();
@ -98,8 +102,7 @@ void BikeSystem::start() {
resetEvent.period(kResetTaskPeriod); resetEvent.period(kResetTaskPeriod);
resetEvent.post(); resetEvent.post();
Event<void()> temperatureEvent(&eventQueue, Event<void()> temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask));
callback(this, &BikeSystem::temperatureTask));
temperatureEvent.delay(kTemperatureTaskDelay); temperatureEvent.delay(kTemperatureTaskDelay);
temperatureEvent.period(kTemperatureTaskPeriod); temperatureEvent.period(kTemperatureTaskPeriod);
temperatureEvent.post(); temperatureEvent.post();
@ -109,14 +112,14 @@ void BikeSystem::start() {
display2Event.period(kDisplayTask2Period); display2Event.period(kDisplayTask2Period);
display2Event.post(); display2Event.post();
#if !defined(MBED_TEST_MODE) #if !defined(MBED_TEST_MODE)
Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask));
cpuEvent.delay(kCPUTaskDelay); cpuEvent.delay(kCPUTaskDelay);
cpuEvent.period(kCPUTaskPeriod); cpuEvent.period(kCPUTaskPeriod);
cpuEvent.post(); cpuEvent.post();
#endif #endif
eventQueue.dispatch_forever(); eventQueue.dispatch_forever();
} }
void BikeSystem::onReset() { void BikeSystem::onReset() {
@ -159,7 +162,8 @@ void BikeSystem::gearTask() {
_currentGearSize = _gearDevice.getCurrentGearSize(); _currentGearSize = _gearDevice.getCurrentGearSize();
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime
);
} }
void BikeSystem::speedDistanceTask() { void BikeSystem::speedDistanceTask() {
@ -169,25 +173,29 @@ void BikeSystem::speedDistanceTask() {
_speedometer.setCurrentRotationTime(pedalRotationTime); _speedometer.setCurrentRotationTime(pedalRotationTime);
_speedometer.setGearSize(_currentGearSize); _speedometer.setGearSize(_currentGearSize);
_currentSpeed = _speedometer.getCurrentSpeed(); _currentSpeed = _speedometer.getCurrentSpeed();
_traveledDistance = _speedometer.getDistance(); _traveledDistance = _speedometer.getDistance();
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime
);
} }
void BikeSystem::temperatureTask() { void BikeSystem::temperatureTask() {
auto taskStartTime = _timer.elapsed_time(); auto taskStartTime = _timer.elapsed_time();
// tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count()); //tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count());
// no need to protect access to data members (single threaded) // no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature(); _currentTemperature = _sensorDevice.readTemperature();
// tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count()); //tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count());
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
@ -215,8 +223,11 @@ void BikeSystem::displayTask1() {
_displayDevice.displaySpeed(_currentSpeed); _displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance); _displayDevice.displayDistance(_traveledDistance);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
@ -227,13 +238,18 @@ void BikeSystem::displayTask2() {
_displayDevice.displayTemperature(_currentTemperature); _displayDevice.displayTemperature(_currentTemperature);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>( ThisThread::sleep_for(
kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime))); std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime)
)
);
_taskLogger.logPeriodAndExecutionTime( _taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime);
} }
void BikeSystem::cpuTask() { _cpuLogger.printStats(); } void BikeSystem::cpuTask() {
_cpuLogger.printStats();
}
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -25,9 +25,9 @@
#pragma once #pragma once
// from advembsof // from advembsof
#include "cpu_logger.hpp"
#include "display_device.hpp" #include "display_device.hpp"
#include "task_logger.hpp" #include "task_logger.hpp"
#include "cpu_logger.hpp"
// from common // from common
#include "sensor_device.hpp" #include "sensor_device.hpp"
@ -78,18 +78,18 @@ class BikeSystem {
bool _stopFlag = false; bool _stopFlag = false;
std::chrono::microseconds _resetTime = std::chrono::microseconds::zero(); std::chrono::microseconds _resetTime = std::chrono::microseconds::zero();
volatile bool _resetFlag = false; volatile bool _resetFlag = false;
// timer instance used for loggint task time and used by ResetDevice // timer instance used for loggint task time and used by ResetDevice
Timer _timer; Timer _timer;
// data member that represents the device for manipulating the gear // data member that represents the device for manipulating the gear
GearDevice _gearDevice; GearDevice _gearDevice;
uint8_t _currentGear = bike_computer::kMinGear; uint8_t _currentGear = bike_computer::kMinGear;
uint8_t _currentGearSize = bike_computer::kMinGearSize; uint8_t _currentGearSize = bike_computer::kMinGearSize;
// data member that represents the device for manipulating the pedal rotation // data member that represents the device for manipulating the pedal rotation
// speed/time // speed/time
PedalDevice _pedalDevice; PedalDevice _pedalDevice;
float _currentSpeed = 0.0f; float _currentSpeed = 0.0f;
float _traveledDistance = 0.0f; float _traveledDistance = 0.0f;
// data member that represents the device used for resetting // data member that represents the device used for resetting
ResetDevice _resetDevice; ResetDevice _resetDevice;
@ -108,4 +108,4 @@ class BikeSystem {
advembsof::CPULogger _cpuLogger; advembsof::CPULogger _cpuLogger;
}; };
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -38,12 +38,17 @@
namespace static_scheduling_with_event { namespace static_scheduling_with_event {
GearDevice::GearDevice() { GearDevice::GearDevice() {
disco::Joystick::getInstance().setUpCallback(callback(this, &GearDevice::onUp)); disco::Joystick::getInstance().setUpCallback(
disco::Joystick::getInstance().setDownCallback(callback(this, &GearDevice::onDown)); callback(this, &GearDevice::onUp));
disco::Joystick::getInstance().setDownCallback(
callback(this, &GearDevice::onDown));
} }
uint8_t GearDevice::getCurrentGear() { return core_util_atomic_load_u8(&_currentGear); } uint8_t GearDevice::getCurrentGear() {
return core_util_atomic_load_u8(&_currentGear);
}
uint8_t GearDevice::getCurrentGearSize() const { uint8_t GearDevice::getCurrentGearSize() const {
return bike_computer::kMaxGearSize - core_util_atomic_load_u8(&_currentGear); return bike_computer::kMaxGearSize - core_util_atomic_load_u8(&_currentGear);
@ -61,4 +66,4 @@ void GearDevice::onDown() {
} }
} }
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -33,7 +33,7 @@ namespace static_scheduling_with_event {
class GearDevice { class GearDevice {
public: public:
GearDevice(); // NOLINT(runtime/references) explicit GearDevice(); // NOLINT(runtime/references)
// make the class non copyable // make the class non copyable
GearDevice(GearDevice&) = delete; GearDevice(GearDevice&) = delete;
@ -51,4 +51,4 @@ class GearDevice {
volatile uint8_t _currentGear = bike_computer::kMinGear; volatile uint8_t _currentGear = bike_computer::kMinGear;
}; };
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -1,26 +1,12 @@
// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**************************************************************************** /****************************************************************************
* @file pedal_device.cpp * @file pedal_device.cpp
* @author Rémi Heredero <remi@heredero.ch> * @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com> * @author Yann Sierro <yannsierro.pro@gmail.com>
* *
* @brief Pedal Device implementation (static scheduling) * @brief Pedal Device implementation (static scheduling)
* @date 2024-11-17 * @date 2024-11-17
* @version 1.1.0 * @version 1.1.0
****************************************************************************/ ****************************************************************************/
#include "pedal_device.hpp" #include "pedal_device.hpp"
@ -36,34 +22,41 @@
namespace static_scheduling_with_event { namespace static_scheduling_with_event {
PedalDevice::PedalDevice() { PedalDevice::PedalDevice() {
disco::Joystick::getInstance().setLeftCallback(callback(this, &PedalDevice::onLeft)); disco::Joystick::getInstance().setLeftCallback(
disco::Joystick::getInstance().setRightCallback( callback(this, &PedalDevice::onLeft)
callback(this, &PedalDevice::onRight)); );
} disco::Joystick::getInstance().setRightCallback(
callback(this, &PedalDevice::onRight)
);
}
std::chrono::milliseconds PedalDevice::getCurrentRotationTime() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
return bike_computer::kMinPedalRotationTime +
currentStep * bike_computer::kDeltaPedalRotationTime;
}
void PedalDevice::increaseRotationSpeed() { std::chrono::milliseconds PedalDevice::getCurrentRotationTime() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
if (currentStep > 0) { return bike_computer::kMinPedalRotationTime + currentStep * bike_computer::kDeltaPedalRotationTime;
core_util_atomic_decr_u32(&_currentStep, 1);
} }
}
void PedalDevice::decreaseRotationSpeed() { void PedalDevice::increaseRotationSpeed() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
if (currentStep < bike_computer::kNbrOfSteps) { if (currentStep > 0) {
core_util_atomic_incr_u32(&_currentStep, 1); core_util_atomic_decr_u32(&_currentStep, 1);
}
} }
void PedalDevice::decreaseRotationSpeed() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
if (currentStep < bike_computer::kNbrOfSteps) {
core_util_atomic_incr_u32(&_currentStep, 1);
}
}
void PedalDevice::onLeft() {
decreaseRotationSpeed();
}
void PedalDevice::onRight() {
increaseRotationSpeed();
}
} }
void PedalDevice::onLeft() { decreaseRotationSpeed(); }
void PedalDevice::onRight() { increaseRotationSpeed(); }
} // namespace static_scheduling_with_event

View File

@ -51,9 +51,10 @@ class PedalDevice {
// data members // data members
volatile uint32_t _currentStep = static_cast<uint32_t>( volatile uint32_t _currentStep = static_cast<uint32_t>(
(bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime) (
.count() / bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime
bike_computer::kDeltaPedalRotationTime.count()); ).count() / bike_computer::kDeltaPedalRotationTime.count()
);
}; };
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -1,26 +1,12 @@
// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**************************************************************************** /****************************************************************************
* @file reset_device.cpp * @file reset_device.cpp
* @author Rémi Heredero <remi@heredero.ch> * @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com> * @author Yann Sierro <yannsierro.pro@gmail.com>
* *
* @brief Reset Device implementation (static scheduling with event) * @brief Reset Device implementation (static scheduling with event)
* @date 2024-11-17 * @date 2024-11-17
* @version 1.1.0 * @version 1.1.0
****************************************************************************/ ****************************************************************************/
#include "reset_device.hpp" #include "reset_device.hpp"
@ -35,14 +21,16 @@
static constexpr uint8_t kPolarityPressed = 1; static constexpr uint8_t kPolarityPressed = 1;
#endif #endif
#if MBED_CONF_MBED_TRACE_ENABLE #if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "ResetDevice" #define TRACE_GROUP "ResetDevice"
#endif // MBED_CONF_MBED_TRACE_ENABLE #endif // MBED_CONF_MBED_TRACE_ENABLE
namespace static_scheduling_with_event { namespace static_scheduling_with_event {
ResetDevice::ResetDevice(Callback<void()> cb) : _resetButton(PUSH_BUTTON) { ResetDevice::ResetDevice(Callback<void()> cb) : _resetButton(PUSH_BUTTON) {
_resetButton.fall(cb); _resetButton.fall(cb);
} }
} // namespace static_scheduling_with_event
}

View File

@ -39,9 +39,10 @@ class ResetDevice {
ResetDevice& operator=(ResetDevice&) = delete; ResetDevice& operator=(ResetDevice&) = delete;
private: private:
// data members // data members
// instance representing the reset button // instance representing the reset button
InterruptIn _resetButton; InterruptIn _resetButton;
}; };
} // namespace static_scheduling_with_event } // namespace static_scheduling

View File

@ -1 +0,0 @@
https://github.com/SergeAyer/update-client#82fe2add70c714d9ce943f1a7dc5fda7dba75dba