Compare commits

..

5 Commits

Author SHA1 Message Date
86deb5420b
ADD my candidate applications
Some checks failed
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-bike-system) (push) Failing after 2s
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-sensor-device) (push) Failing after 3s
Build test application / build-cli-v1 (debug, DISCO_H747I, tests-bike-computer-speedometer) (push) Failing after 3s
2025-01-04 15:32:00 +01:00
f6e3413cf6
ADD library update-client 2025-01-04 15:31:25 +01:00
488d7532e7
ADD pre-commit config 2025-01-04 15:14:28 +01:00
6e79ced7ff
ADD minimal bootloader (main.cpp) 2024-12-31 12:02:40 +01:00
890edc211a
ADD minimal bootloader 2024-12-31 11:54:14 +01:00
39 changed files with 343 additions and 1551 deletions

3
.gitignore vendored
View File

@ -4,5 +4,6 @@ projectfiles
*.py*
BUILD
mbed-os
DISCO_H747I
DISCO_h747i
advdembsof_library
update-client

View File

@ -1,4 +1,4 @@
files: ^main.cpp|^static_scheduling|^static_scheduling_with_event|^TESTS|^multi_tasking|^common
files: ^main.cpp|^static_scheduling|^static_scheduling_with_event|^TESTS
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0

View File

@ -1,5 +0,0 @@
# 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
View File

@ -1,165 +0,0 @@
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

@ -23,27 +23,25 @@ Test sensor libraries :
mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run
```
## Run static scheduling
## Run static scheduling
On `.mbedignore` put at the end of the file
```
static_scheduling_with_event/*
multi_tasking/*
```
On main.cpp include `"static_scheduling/bike_system.hpp"` and use :
On main.cpp include `"static_scheduling/bike_system.hpp"` and use :
```cpp
static_scheduling::BikeSystem bikeSystem;
bikeSystem.start();
```
## Run static scheduling with event queue
On `.mbedignore` put at the end of the file :
On `.mbedignore` put at the end of the file :
```
static_scheduling_with_event/*
multi_tasking/*
```
On main.cpp include `"static_scheduling/bike_system.hpp"` and use :
On main.cpp include `"static_scheduling/bike_system.hpp"` and use :
```cpp
static_scheduling::BikeSystem bikeSystem;
bikeSystem.startWithEventQueue();
@ -53,23 +51,9 @@ bikeSystem.startWithEventQueue();
On `.mbedignore` put at the end of the file
```
static_scheduling/*
static_scheduling_with_event/*
```
On main.cpp include `"multi_tasking/bike_system.hpp"` and use :
```cpp
multi_tasking::BikeSystem bikeSystem;
bikeSystem.start();
```
## Run multi-tasking
On `.mbedignore` put at the end of the file
```
static_scheduling/*
multi_tasking/*
```
On main.cpp include `"static_scheduling_with_event/bike_system.hpp"` and use :
On main.cpp include `"static_scheduling_with_event/bike_system.hpp"` and use :
```cpp
static_scheduling_with_event::BikeSystem bikeSystem;
bikeSystem.start();
@ -79,7 +63,7 @@ bikeSystem.start();
## Question 1
`If you print CPU statistics at the end of every major cycle (in the super-loop), what CPU usage do you observe? How can you explain the observed CPU uptime?`
We observe a 100% usage because on each CPU cycle it compare if time is done.
We observe a 100% usage because on each CPU cycle it compare if time is done.
## Question 2
`If you run the program after the change from busy wait to sleep calls, what CPU usage do you observe? How can you explain the observed CPU uptime?`
@ -89,7 +73,7 @@ We can observe only a usage of 75% because the CPU is more on Idle with Thread s
## Question 3
`If you run the static_scheduling_with_event program, what CPU usage do you observe? How can you explain the observed CPU uptime?`
We observe a light usage of 1% of CPU. The CPU is now sleeping all the time and doing small task only on event.
We observe a light usage of 1% of CPU. The CPU is now sleeping all the time and doing small task only on event.
## Question 4
`When you run multiple tests for computing the response time of the reset event, what do you observe? Is there an improvement as compared to the static_scheduling::BikeSystem implementation?`
@ -100,22 +84,7 @@ We observe a light usage of 1% of CPU. The CPU is now sleeping all the time and
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.
# Multi-tasking
## Question 1
We have computed the elapsed time between the event is sent by the interruption until it is executed :
|Rtos priority |time |
|---|---|
|osPriorityBelowNormal |13 usecs |
|osPriorityNormal |13 usecs |
|osPriorityAboveNormal |13 usecs |
To abtain these values, we have to consider that there is a isr thread. He dispatchs all the events from the gear device and the reset device. The rest is processed by the main thread.
Main of the time, it meares these values. But sometimes, higher values can appear. These values doesn't change because there isn't often more than one event in the queue.
# 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
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

@ -23,23 +23,15 @@
***************************************************************************/
#include <chrono>
#include <cstdint>
#include "gear_device.hpp"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "mbed_trace.h" // NOLINT
#include "multi_tasking/bike_system.hpp"
#include "static_scheduling/bike_system.hpp"
#include "static_scheduling_with_event/bike_system.hpp"
#include "task_logger.hpp"
#include "unity/unity.h"
#include "utest/utest.h"
#if defined(MBED_CONF_MBED_TRACE_ENABLE)
#define TRACE_GROUP "TEST_BIKE_SYSTEM"
#endif // MBED_CONF_MBED_TRACE_ENAB
namespace utest {
namespace v1 {
@ -148,235 +140,6 @@ static void test_bike_system_with_event() {
}
}
// test_multi_tasking_bike_system handler function
static void test_multi_tasking_bike_system() {
tr_info("test multi tasking bike system");
// create the BikeSystem instance
multi_tasking::BikeSystem bikeSystem;
// run the bike system in a separate thread
Thread thread;
osStatus status =
thread.start(callback(&bikeSystem, &multi_tasking::BikeSystem::start));
if (status != osOK) {
tr_error("Thread bike system is not OK !");
}
tr_info("bike system has started");
// let the bike system run for 20 secs
ThisThread::sleep_for(20s);
// check whether scheduling was correct
// Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex,
// kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index
// When we use event handling, we do not check the computation time
constexpr std::chrono::microseconds taskPeriods[] = {
800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us};
// allow for 2 msecs offset (with EventQueue)
constexpr uint64_t kDeltaUs = 2000;
// stop the bike system
bikeSystem.stop();
thread.terminate();
tr_info("Threads have stopped");
TEST_ASSERT_UINT64_WITHIN(
kDeltaUs,
taskPeriods[advembsof::TaskLogger::kTemperatureTaskIndex].count(),
bikeSystem.getTaskLogger()
.getPeriod(advembsof::TaskLogger::kTemperatureTaskIndex)
.count());
TEST_ASSERT_UINT64_WITHIN(
kDeltaUs,
taskPeriods[advembsof::TaskLogger::kDisplayTask1Index].count(),
bikeSystem.getTaskLogger()
.getPeriod(advembsof::TaskLogger::kDisplayTask1Index)
.count());
}
// test_reset_multi_tasking_bike_system handler function
Timer timer;
static std::chrono::microseconds resetTime = std::chrono::microseconds::zero();
static EventFlags eventFlags;
static constexpr uint32_t kResetEventFlag = (1UL << 0);
static void resetCallback() {
resetTime = timer.elapsed_time();
eventFlags.set(kResetEventFlag);
}
static void test_reset_multi_tasking_bike_system() {
tr_info("test reset multi tasking bike system");
// create the BikeSystem instance
multi_tasking::BikeSystem bikeSystem;
// run the bike system in a separate thread
Thread thread;
osStatus status =
thread.start(callback(&bikeSystem, &multi_tasking::BikeSystem::start));
if (status != osOK) {
tr_error("Thread bike system is not OK !");
}
tr_info("Bike system has started");
// let the bike system run for 2 secs
ThisThread::sleep_for(2s);
// test reset on BikeSystem
bikeSystem.getSpeedometer().setOnResetCallback(resetCallback);
// start the timer instance
timer.start();
// check for reset response time
constexpr uint8_t kNbrOfResets = 10;
std::chrono::microseconds lastResponseTime = std::chrono::microseconds::zero();
for (uint8_t i = 0; i < kNbrOfResets; i++) {
tr_info("Reset test N°%d", i);
// take time before reset
auto startTime = timer.elapsed_time();
// reset the BikeSystem
bikeSystem.onReset();
// wait for resetCallback to be called
eventFlags.wait_all(kResetEventFlag);
// get the response time and check it
auto responseTime = resetTime - startTime;
// cppcheck generates an internal error with 20us
constexpr std::chrono::microseconds kMaxExpectedResponseTime(20);
tr_info("Reset task: response time is %lld usecs\n, expected : %lld",
responseTime.count(),
kMaxExpectedResponseTime.count());
TEST_ASSERT_TRUE(responseTime.count() <= kMaxExpectedResponseTime.count());
// jitter of 20us is accepted
constexpr uint64_t kDeltaUs = 4;
constexpr std::chrono::microseconds kMaxExpectedJitter(3);
if (i > 0) {
auto jitter = responseTime - lastResponseTime;
tr_info("Reset task: jitter is %lld usecs\n", std::abs(jitter.count()));
TEST_ASSERT_UINT64_WITHIN(
kDeltaUs, kMaxExpectedJitter.count(), std::abs(jitter.count()));
}
lastResponseTime = responseTime;
// let the bike system run for 2 secs
ThisThread::sleep_for(2s);
}
// stop the bike system
bikeSystem.stop();
thread.terminate();
tr_info("Threads have stopped");
timer.stop();
}
Timer timerGear;
static std::chrono::microseconds gearTime = std::chrono::microseconds::zero();
static EventFlags eventGearFlags;
static constexpr uint32_t kGearEventFlag = (1UL << 0);
constexpr uint8_t kNbrOfGear = 9;
static void onGearChange() {
gearTime = timerGear.elapsed_time();
eventGearFlags.set(kGearEventFlag);
tr_info("Gear changed");
}
static void gearTest(Callback<void()> gearChange) {
// std::chrono::microseconds lastResponseTime = std::chrono::microseconds::zero();
for (uint8_t i = 1; i < kNbrOfGear; i++) {
tr_info("Gear test N°%d", i);
// take time before increase the gear
auto startTime = timerGear.elapsed_time();
// change the gear with the callback
tr_info("Change gear");
gearChange();
// wait flag
eventGearFlags.wait_all(kGearEventFlag);
// get the response time and check it
auto responseTime = gearTime - startTime;
constexpr std::chrono::microseconds kMaxExpectedResponseTime(100000);
tr_info("Change gear task: response time is %lld usecs\n, expected : %lld",
responseTime.count(),
kMaxExpectedResponseTime.count());
TEST_ASSERT_TRUE(responseTime.count() <= kMaxExpectedResponseTime.count());
// jitter of 20us is accepted
// constexpr uint64_t kDeltaUs = 2000;
// constexpr std::chrono::microseconds kMaxExpectedJitter(4000);
// if (i > 1) {
// auto jitter = responseTime - lastResponseTime;
// tr_info("Gear task: jitter is %lld usecs\n", std::abs(jitter.count()));
// TEST_ASSERT_UINT64_WITHIN(
// kDeltaUs, kMaxExpectedJitter.count(), std::abs(jitter.count()));
// }
// lastResponseTime = responseTime;
// let the bike system run for 2 secs
ThisThread::sleep_for(2s);
}
}
static void test_gear_multi_tasking_bike_system() {
tr_info("test reset multi tasking bike system");
// create the BikeSystem instance
multi_tasking::BikeSystem bikeSystem;
// run the bike system in a separate thread
Thread thread;
osStatus status =
thread.start(callback(&bikeSystem, &multi_tasking::BikeSystem::start));
if (status != osOK) {
tr_error("Thread bike system is not OK !");
}
tr_info("Bike system has started");
// let the bike system run for 2 secs
ThisThread::sleep_for(2s);
// get the gear device to call onUp and onDown functions
multi_tasking::GearDevice& gearDevice = bikeSystem.getGearDevice();
// set callback for response time measuring
bikeSystem.setCallbackGearChage(onGearChange);
// start the timer instance
timerGear.start();
// test timing incresing the gear
tr_info("Test incresing gear");
gearTest(callback(&gearDevice, &multi_tasking::GearDevice::onUp));
// test timing decreasing the gear
tr_info("Test decreasing gear");
gearTest(callback(&gearDevice, &multi_tasking::GearDevice::onDown));
// stop the bike system
bikeSystem.stop();
thread.terminate();
tr_info("Threads have stopped");
timerGear.stop();
}
static 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
// or the name of our Python file)
@ -389,10 +152,7 @@ static status_t greentea_setup(const size_t number_of_cases) {
static Case cases[] = {
Case("test bike system", test_bike_system),
Case("test bike system with event queue", test_bike_system_event_queue),
Case("test bike system with event", test_bike_system_with_event),
Case("test multi-tasking bike system", test_multi_tasking_bike_system),
Case("test reset multi-tasking bike system", test_reset_multi_tasking_bike_system),
Case("test gear multi-tasking bike system", test_gear_multi_tasking_bike_system),
Case("test bike system with event handling", test_bike_system_with_event),
};
static Specification specification(greentea_setup, cases);
@ -400,9 +160,4 @@ static Specification specification(greentea_setup, cases);
}; // namespace v1
}; // namespace utest
int main() {
#if defined(MBED_CONF_MBED_TRACE_ENABLE)
mbed_trace_init();
#endif
return !utest::v1::Harness::run(utest::v1::specification);
}
int main() { return !utest::v1::Harness::run(utest::v1::specification); }

View File

@ -52,8 +52,9 @@ static constexpr std::chrono::milliseconds kMaxPedalRotationTime = 1500ms;
static constexpr std::chrono::milliseconds kDeltaPedalRotationTime = 25ms;
static constexpr uint32_t kNbrOfSteps = static_cast<uint32_t>(
(bike_computer::kMaxPedalRotationTime - bike_computer::kMinPedalRotationTime)
.count() /
bike_computer::kDeltaPedalRotationTime.count());
(
bike_computer::kMaxPedalRotationTime - bike_computer::kMinPedalRotationTime
).count() / bike_computer::kDeltaPedalRotationTime.count()
);
} // namespace bike_computer
} // namespace bike_computer

View File

@ -1,37 +1,21 @@
// 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 speedometer_device.cpp
* @author Serge Ayer <serge.ayer@hefr.ch>
*
* @brief WheelCounterDevice implementation (static scheduling)
*
* @date 2023-08-20
* @version 1.0.0
***************************************************************************/
#include "sensor_device.hpp"
namespace bike_computer {
SensorDevice::SensorDevice() : _hdc1000(I2C_SDA, I2C_SCL, STMOD_11) {}
SensorDevice::SensorDevice() : _hdc1000(I2C_SDA, I2C_SCL, STMOD_11)
{}
bool SensorDevice::init() { return this->_hdc1000.probe(); }
bool SensorDevice::init() {
return this->_hdc1000.probe();
}
float SensorDevice::readTemperature(void) { return this->_hdc1000.getTemperature(); }
float SensorDevice::readTemperature(void) {
return this->_hdc1000.getTemperature();
}
float SensorDevice::readHumidity(void) { return this->_hdc1000.getHumidity(); }
float SensorDevice::readHumidity(void) {
return this->_hdc1000.getHumidity();
}
} // bike_computer
} // namespace bike_computer

View File

@ -46,4 +46,4 @@ class SensorDevice {
advembsof::HDC1000 _hdc1000;
};
} // namespace bike_computer
} // namespace bike_computer

View File

@ -24,8 +24,9 @@
#include "speedometer.hpp"
#include "static_scheduling/gear_device.hpp"
#include <chrono>
#include <cstddef>
#include <ratio>
// from disco_h747i/wrappers
@ -79,12 +80,7 @@ float Speedometer::getDistance() {
}
void Speedometer::reset() {
#if defined(MBED_TEST_MODE)
if (_cbOnReset != NULL) {
_cbOnReset();
}
#endif
// TODO : done
this->_totalDistanceMutex.lock();
this->_totalDistance = 0.0f;
this->_totalDistanceMutex.unlock();
@ -100,7 +96,6 @@ float Speedometer::getTraySize() const { return kTraySize; }
std::chrono::milliseconds Speedometer::getCurrentPedalRotationTime() const {
return _pedalRotationTime;
}
void Speedometer::setOnResetCallback(mbed::Callback<void()> cb) { _cbOnReset = cb; }
#endif // defined(MBED_TEST_MODE)
@ -112,14 +107,11 @@ void Speedometer::computeSpeed() {
// = 6.99m If you ride at 80 pedal turns / min, you run a distance of 6.99 * 80 / min
// ~= 560 m / min = 33.6 km/h
// Distance run with one pedal turn = tray size / rear gear size * circumference of
// the wheel
// TODO : done
//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);
float pedal_rotation_per_hour =
ms_in_hour /
std::chrono::duration_cast<std::chrono::milliseconds>(_pedalRotationTime).count();
float gear_ratio =
static_cast<float>(kTraySize) / static_cast<float>(this->_gearSize);
float pedal_rotation_per_hour = ms_in_hour / std::chrono::duration_cast<std::chrono::milliseconds>(_pedalRotationTime).count();
float gear_ratio = static_cast<float>(kTraySize) / static_cast<float>(this->_gearSize);
float wheel_dist_km = static_cast<float>(this->kWheelCircumference) / 1000.0;
this->_currentSpeed = gear_ratio * wheel_dist_km * pedal_rotation_per_hour;
}
@ -133,13 +125,14 @@ void Speedometer::computeDistance() {
// ~= 560 m / min = 33.6 km/h. We then multiply the speed by the time for getting the
// distance traveled.
// TODO : done
Speedometer::computeSpeed();
// compute distance
const std::chrono::microseconds timeNow = _timer.elapsed_time();
const std::chrono::microseconds timeNow = _timer.elapsed_time();
const std::chrono::microseconds timeDiff = timeNow - _lastTime;
constexpr float ms_in_hour = static_cast<float>(3600 * 1000);
float traveled_dist = _currentSpeed * timeDiff.count() / (ms_in_hour * 1000.0 /*μs*/);
constexpr float ms_in_hour = static_cast<float>(3600 * 1000);
float traveled_dist = _currentSpeed * timeDiff.count() / (ms_in_hour*1000.0/*μs*/);
this->_totalDistanceMutex.lock();
this->_totalDistance += traveled_dist;

View File

@ -55,7 +55,6 @@ class Speedometer {
float getTraySize() const;
std::chrono::milliseconds getCurrentPedalRotationTime() const;
void setOnResetCallback(mbed::Callback<void()> cb);
mbed::Callback<void()> _cbOnReset = NULL;
#endif // defined(MBED_TEST_MODE)
private:
@ -80,11 +79,13 @@ class Speedometer {
float _currentSpeed = 0.0f;
Mutex _totalDistanceMutex;
float _totalDistance = 0.0f;
uint8_t _gearSize = bike_computer::kMaxGearSize;
uint8_t _gearSize = 1;
Thread _thread;
#if defined(MBED_TEST_MODE)
mbed::Callback<void()> _cb;
#endif
};
} // namespace bike_computer
} // namespace bike_computer

View File

@ -5,11 +5,12 @@
#if !MBED_TEST_MODE
#include "mbed.h" // NOLINT
#include "mbed_trace.h" // NOLINT
#include "mbed.h" // NOLINT
#include "mbed_trace.h"
// #include "static_scheduling/bike_system.hpp"
#include "FlashIAPBlockDevice.h"
#include "static_scheduling_with_event/bike_system.hpp"
// #include "multi_tasking/bike_system.hpp"
#include "update-client/usb_serial_uc.hpp"
#if defined(MBED_CONF_MBED_TRACE_ENABLE)
#define TRACE_GROUP "MAIN"
@ -20,14 +21,25 @@ int main() {
mbed_trace_init();
#endif
tr_info("Start");
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;
// bikeSystem.start();
static_scheduling_with_event::BikeSystem bikeSystem;
bikeSystem.start();
// multi_tasking::BikeSystem bikeSystem;
// bikeSystem.start();
tr_debug("Starting Bike System");
// bikeSystem.startWithEventQueue();
bikeSystem.start();
while (true) {
}
}
#endif // MBED_TEST_MODE

Binary file not shown.

View File

@ -5,4 +5,4 @@ projectfiles
mbed-os
BUILD
!BUILD/DISCO_H747I/GCC_ARM/mbed-os-bootloader.bin
update-client

View File

@ -1,8 +1,10 @@
#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"
#define TRACE_GROUP "BOOTLOADER"
#endif // MBED_CONF_MBED_TRACE_ENABLE
#if MBED_CONF_MBED_TRACE_ENABLE
@ -22,14 +24,30 @@ int main() {
mbed_trace_print_function_set(boot_debug);
#endif // MBED_CONF_MBED_TRACE_ENABLE
tr_debug("BikeComputer bootloader\r\n");
tr_debug("BikeComputer bootloader\r");
// at this stage we directly branch to the main application
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)\r\n", POST_APPLICATION_ADDR, (uint32_t) sp, (uint32_t) pc);
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");
mbed_start_application(POST_APPLICATION_ADDR);
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);
return 0;
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,6 +1,7 @@
{
"macros": [
"MBED_CONF_MBED_TRACE_FEA_IPV6=0"
"MBED_CONF_MBED_TRACE_FEA_IPV6=0",
"MBED_BOOTLOADER_FLASH_BANK_SIZE=MBED_ROM_SIZE/2"
],
"config": {
"main-stack-size": {
@ -17,7 +18,10 @@
"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
"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",

View File

@ -0,0 +1,22 @@
{
"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

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

View File

@ -1,27 +1,34 @@
{
"macros": ["MBED_CONF_MBED_TRACE_FEA_IPV6=0"],
"config": {
"main-stack-size": {
"value": 8192
}
},
"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
"macros": [
"MBED_CONF_MBED_TRACE_FEA_IPV6=0",
"MBED_BOOTLOADER_FLASH_BANK_SIZE=MBED_ROM_SIZE/2",
"USE_USB_SERIAL_UC=1"
],
"config": {
"main-stack-size": {
"value": 4096
}
},
"DISCO_H747I": {
"mbed-trace.enable": true,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
"target.bootloader_img": "./mbed-os-bootloader/BUILD/DISCO_H747I/GCC_ARM/mbed-os-bootloader.bin",
"target.app_offset": "0x20000"
"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": {
"mbed-trace.enable": true,
"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"
}
}
}
}
}

22
mbed_lib.json Normal file
View File

@ -0,0 +1,22 @@
{
"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,406 +0,0 @@
// 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 bike_system.cpp
* @author Serge Ayer <serge.ayer@hefr.ch>
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Bike System implementation (static scheduling)
*
* @date 2023-11-15
* @version 1.1.0
***************************************************************************/
#include "bike_system.hpp"
#include <chrono>
#include <cstdint>
#include "cmsis_os.h"
#include "common/constants.hpp"
#include "mbed_trace.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "BikeSystem"
#endif // MBED_CONF_MBED_TRACE_ENABLE
namespace multi_tasking {
static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms;
static constexpr std::chrono::milliseconds kDisplayTask1Period = 1600ms;
static constexpr std::chrono::milliseconds kDisplayTask1Delay = 300ms;
static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime = 200ms;
static constexpr std::chrono::milliseconds kTemperatureTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kTemperatureTaskDelay = 1100ms;
static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 100ms;
static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms;
static constexpr std::chrono::milliseconds kCPUTaskDelay = 0ms;
BikeSystem::BikeSystem()
: _timer(),
_isrEventQueue(),
_eventQueue(),
_mailPedalDevice(),
_mailGearDevice(),
_mutexGearSize(),
_mutexGear(),
_mutexSpeed(),
_mutexDistance(),
_mutexSpeedometer(),
_isrEventThread(osPriorityAboveNormal, OS_STACK_SIZE, nullptr, "ISR_Event"),
_speedDistanceThread(
osPriorityNormal, OS_STACK_SIZE, nullptr, "Speed_distance_Task"),
_gearTaskThread(osPriorityAboveNormal, OS_STACK_SIZE, nullptr, "Gear_Task"),
_gearDevice(&_mailGearDevice, _timer),
_pedalDevice(&_mailPedalDevice, _timer),
_resetDevice(callback(this, &BikeSystem::onReset)),
_displayDevice(),
_speedometer(_timer),
_sensorDevice(),
_taskLogger(),
_cpuLogger(_timer) {}
#if defined(MBED_TEST_MODE)
const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; }
bike_computer::Speedometer& BikeSystem::getSpeedometer() {
// ENTER CRITICAL SECTION
_mutexSpeedometer.lock();
bike_computer::Speedometer& speedometer = _speedometer;
_mutexSpeedometer.unlock();
// END CRITICAL SECTION
return speedometer;
}
GearDevice& BikeSystem::getGearDevice() { return _gearDevice; }
void BikeSystem::setCallbackGearChage(Callback<void()> cbGearChange) {
_cbGearChange = cbGearChange;
}
#endif // defined(MBED_TEST_MODE)
void BikeSystem::init() {
// start the timer
_timer.start();
// initialize the lcd display
disco::ReturnCode rc = _displayDevice.init();
if (rc != disco::ReturnCode::Ok) {
tr_error("Ffalseailed to initialized the lcd display: %d", static_cast<int>(rc));
}
// initialize the sensor device
bool present = _sensorDevice.init();
if (!present) {
tr_error("Sensor not present or initialization failed");
}
// enable/disable task logging
bool runTaskLogger = false;
#if defined(MBED_TEST_MODE)
runTaskLogger = true;
#endif
_taskLogger.enable(runTaskLogger);
}
void BikeSystem::start() {
init();
Event<void()> temperatureEvent(&_eventQueue,
callback(this, &BikeSystem::temperatureTask));
temperatureEvent.delay(kTemperatureTaskDelay);
temperatureEvent.period(kTemperatureTaskPeriod);
temperatureEvent.post();
Event<void()> displayEvent(&_eventQueue, callback(this, &BikeSystem::displayTask));
displayEvent.delay(kDisplayTask1Delay);
displayEvent.period(kDisplayTask1Period);
displayEvent.post();
osStatus status =
_isrEventThread.start(callback(this, &BikeSystem::dispatch_isr_events));
if (status != osOK) {
tr_error("Thread %s started with status %ld",
_isrEventThread.get_name(),
static_cast<int32_t>(status));
}
status =
_speedDistanceThread.start(callback(this, &BikeSystem::loop_speed_distance_task));
if (status != osOK) {
tr_error("Thread %s started with status %ld",
_isrEventThread.get_name(),
static_cast<int32_t>(status));
}
status = _gearTaskThread.start(callback(this, &BikeSystem::loop_gear_task));
if (status != osOK) {
tr_error("Thread %s started with status %ld",
_gearTaskThread.get_name(),
static_cast<int32_t>(status));
}
#if !defined(MBED_TEST_MODE)
Event<void()> cpuEvent(&_eventQueue, callback(this, &BikeSystem::cpuTask));
cpuEvent.delay(kCPUTaskDelay);
cpuEvent.period(kCPUTaskPeriod);
cpuEvent.post();
#endif
// dispatch the main queue in the main thread
dispatch_events();
}
void BikeSystem::stop() {
osStatus status = _isrEventThread.terminate();
status += _speedDistanceThread.terminate();
status += _gearTaskThread.terminate();
if (status != 0) {
tr_error("Stop thread error");
}
tr_info("Bike system has stopped !");
}
/* Callback from isr */
void BikeSystem::onReset() {
_resetTime = _timer.elapsed_time();
Event<void()> resetEvent(&_isrEventQueue, callback(this, &BikeSystem::resetTask));
resetEvent.post();
}
// ISR thread functions
void BikeSystem::resetTask() {
#if !defined(MBED_TEST_MODE)
auto taskStartTime = _timer.elapsed_time();
std::chrono::microseconds responseTime = _timer.elapsed_time() - _resetTime;
tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count());
#endif
// ENTER CRITICAL SECTION
_mutexSpeedometer.lock();
_speedometer.reset();
_mutexSpeedometer.unlock();
// END CRITICAL SECTION
#if !defined(MBED_TEST_MODE)
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime);
#endif
}
// Speed distance thread functions
void BikeSystem::speedDistanceTask() {
auto taskStartTime = _timer.elapsed_time();
pedalMail_t* currentStep = _mailPedalDevice.try_get();
if (currentStep != nullptr) {
const auto pedalRotationTime =
PedalDevice::getCurrentRotationTime(currentStep->step);
// ENTER CRITICAL SECTION
_mutexSpeedometer.lock();
_speedometer.setCurrentRotationTime(pedalRotationTime);
_mutexSpeedometer.unlock();
// END CRITICAL SECTION
std::chrono::microseconds responseTime =
_timer.elapsed_time() - currentStep->callTime;
tr_info("Speed distance task: response time is %" PRIu64 " usecs",
responseTime.count());
osStatus status = _mailPedalDevice.free(currentStep);
if (status != osOK) {
tr_error("free current step in the speed distance tasks doesn't work !");
}
}
// ENTER CRITICAL SECTION
_mutexSpeedometer.lock();
_speedometer.setGearSize(getCurrentGearSize());
_mutexSpeed.lock();
_currentSpeed = _speedometer.getCurrentSpeed();
_mutexSpeed.unlock();
_mutexDistance.lock();
_traveledDistance = _speedometer.getDistance();
_mutexDistance.unlock();
_mutexSpeedometer.unlock();
// END CRITICAL SECTION
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kSpeedDistanceTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime);
}
/* Gear thread functions */
void BikeSystem::gearTask() {
auto taskStartTime = _timer.elapsed_time();
gearMail_t* currentGear = _mailGearDevice.try_get();
if (currentGear != nullptr) {
#if !defined(MBED_TEST_MODE)
std::chrono::microseconds responseTime =
_timer.elapsed_time() - currentGear->callTime;
tr_info("Gear task: response time is %" PRIu64 " usecs", responseTime.count());
#endif
#if defined(MBED_TEST_MODE)
_cbGearChange();
#endif
// ENTER CRITICAL SECTION
_mutexGear.lock();
_currentGear = currentGear->gear;
_mutexGear.unlock();
_mutexGearSize.lock();
_currentGearSize = bike_computer::kMaxGearSize - currentGear->gear;
_mutexGearSize.unlock();
// END CRITICAL SECTION
osStatus status = _mailGearDevice.free(currentGear);
if (status != osOK) {
tr_error("free current gear in the gear tasks doesn't work !");
}
}
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kGearTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime);
}
/* Main thread functions */
void BikeSystem::temperatureTask() {
auto taskStartTime = _timer.elapsed_time();
// no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature();
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
}
void BikeSystem::displayTask() {
auto taskStartTime = _timer.elapsed_time();
// ENTER CRITICAL SECTION
_displayDevice.displayGear(getCurrentGear());
_displayDevice.displaySpeed(getCurrentSpeed());
_displayDevice.displayDistance(getCurrentDistance());
// END CRITICAL SECTION
_displayDevice.displayTemperature(_currentTemperature);
// ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(kDisplayTask1ComputationTime
// - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
}
void BikeSystem::cpuTask() { _cpuLogger.printStats(); }
void BikeSystem::dispatch_isr_events() {
tr_info("Start dispatching isr events");
_isrEventQueue.dispatch_forever();
tr_info("Stop dispatching isr events");
}
void BikeSystem::dispatch_events() {
tr_info("Start dispatching main events");
_eventQueue.dispatch_forever();
tr_info("Stop dispatching main events");
}
void BikeSystem::loop_speed_distance_task() {
tr_info("Start loop speed-distance calculation");
while (true) {
speedDistanceTask();
}
}
void BikeSystem::loop_gear_task() {
tr_info("Start loop gear calculation");
while (true) {
gearTask();
}
}
uint8_t BikeSystem::getCurrentGear() {
uint8_t currentGear;
// ENTER CRITICAL SECTION
_mutexGear.lock();
currentGear = _currentGear;
_mutexGear.unlock();
// END CRITICAL SECTION
return currentGear;
}
uint8_t BikeSystem::getCurrentGearSize() {
uint8_t currentGearSize;
// ENTER CRITICAL SECTION
_mutexGearSize.lock();
currentGearSize = _currentGearSize;
_mutexGearSize.unlock();
// END CRITICAL SECTION
return currentGearSize;
}
float BikeSystem::getCurrentSpeed() {
float currentSpeed;
// ENTER CRITICAL SECTION
_mutexSpeed.lock();
currentSpeed = _currentSpeed;
_mutexSpeed.unlock();
// END CRITICAL SECTION
return currentSpeed;
}
float BikeSystem::getCurrentDistance() {
float currentDistance;
// ENTER CRITICAL SECTION
_mutexDistance.lock();
currentDistance = _traveledDistance;
_mutexDistance.unlock();
// END CRITICAL SECTION
return currentDistance;
}
} // namespace multi_tasking

View File

@ -1,171 +0,0 @@
// 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 bike_system.hpp
* @author Serge Ayer <serge.ayer@hefr.ch>
*
* @brief Bike System header file (static scheduling)
*
* @date 2023-08-20
* @version 1.0.0
***************************************************************************/
#pragma once
// from advembsof
#include "cpu_logger.hpp"
#include "display_device.hpp"
#include "mbed.h"
#include "task_logger.hpp"
// from common
#include "sensor_device.hpp"
#include "speedometer.hpp"
// local
#include "gear_device.hpp"
#include "pedal_device.hpp"
#include "reset_device.hpp"
namespace multi_tasking {
class BikeSystem {
public:
// constructor
BikeSystem();
// make the class non copyable
BikeSystem(BikeSystem&) = delete;
BikeSystem& operator=(BikeSystem&) = delete;
// method called in main() for starting the system
void start();
// method called for stopping the system
void stop();
#if defined(MBED_TEST_MODE)
const advembsof::TaskLogger& getTaskLogger();
bike_computer::Speedometer& getSpeedometer();
GearDevice& getGearDevice();
void setCallbackGearChage(Callback<void()> cbGearChange);
Callback<void()> _cbGearChange;
#endif // defined(MBED_TEST_MODE)
private:
// private methods
void init();
// Main Thread
void temperatureTask();
void displayTask();
void cpuTask();
// ISR Thread
#if defined(MBED_TEST_MODE)
public:
#endif
void onReset();
#if defined(MBED_TEST_MODE)
private:
#endif
void resetTask();
// gear Thread
void gearTask();
// Speed / Distance Thread
void speedDistanceTask();
// GETTER - SETTER
uint8_t getCurrentGear();
uint8_t getCurrentGearSize();
float getCurrentSpeed();
float getCurrentDistance();
void setCurrentGear(uint8_t gear);
// Thread functions
void dispatch_isr_events();
void dispatch_events();
void loop_speed_distance_task();
void loop_gear_task();
// timer instance used for loggint task time and used by ResetDevice
std::chrono::microseconds _resetTime = std::chrono::microseconds::zero();
std::chrono::microseconds _onGearUpTime = std::chrono::microseconds::zero();
std::chrono::microseconds _onGearDownTime = std::chrono::microseconds::zero();
Timer _timer;
// Event queues
EventQueue _isrEventQueue;
EventQueue _eventQueue;
// Mail
Mail<pedalMail_t, 16> _mailPedalDevice;
Mail<gearMail_t, 16> _mailGearDevice;
// mutex for shared resource
Mutex _mutexGearSize;
Mutex _mutexGear;
Mutex _mutexSpeed;
Mutex _mutexDistance;
Mutex _mutexSpeedometer;
// Tread for isr events
Thread _isrEventThread;
Thread _speedDistanceThread;
Thread _gearTaskThread;
// data member that represents the device for manipulating the gear
GearDevice _gearDevice;
//////////////////////////////////////////////////////////////
// shared resources between the main thread and the isr thread
uint8_t _currentGear = bike_computer::kMinGear;
uint8_t _currentGearSize = bike_computer::kMaxGearSize;
//////////////////////////////////////////////////////////////
// data member that represents the device for manipulating the pedal rotation
// speed/time
PedalDevice _pedalDevice;
//////////////////////////////////////////////////////////////
// shared resources between the main thread and the isr thread
float _currentSpeed = 0.0f;
float _traveledDistance = 0.0f;
//////////////////////////////////////////////////////////////
// data member that represents the device used for resetting
ResetDevice _resetDevice;
// data member that represents the device display
advembsof::DisplayDevice _displayDevice;
// data member that represents the device for counting wheel rotations
bike_computer::Speedometer _speedometer;
// data member that represents the sensor device
bike_computer::SensorDevice _sensorDevice;
float _currentTemperature = 0.0f;
// used for logging task info
advembsof::TaskLogger _taskLogger;
// cpu logger to measure cpu usage
advembsof::CPULogger _cpuLogger;
};
} // namespace multi_tasking

View File

@ -1,74 +0,0 @@
// 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 gear_device.cpp
* @author Serge Ayer <serge.ayer@hefr.ch>
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Gear Device implementation (static scheduling)
*
* @date 2023-11-17
* @version 1.1.0
***************************************************************************/
#include "gear_device.hpp"
#include "bike_system.hpp"
// from disco_h747i/wrappers
#include "joystick.hpp"
#include "mbed_atomic.h"
#include "mbed_trace.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "GearDevice"
#endif // MBED_CONF_MBED_TRACE_ENABLE
namespace multi_tasking {
GearDevice::GearDevice(Mail<gearMail_t, 16>* mailBox, Timer& timer)
: _mailBox(mailBox), _timer(timer) {
disco::Joystick::getInstance().setUpCallback(callback(this, &GearDevice::onUp));
disco::Joystick::getInstance().setDownCallback(callback(this, &GearDevice::onDown));
}
void GearDevice::onUp() {
if (_currentGear < bike_computer::kMaxGear) {
core_util_atomic_incr_u8(&_currentGear, 1);
sendMail(core_util_atomic_load_u8(&_currentGear));
}
}
void GearDevice::onDown() {
if (_currentGear > bike_computer::kMinGear) {
core_util_atomic_decr_u8(&_currentGear, 1);
sendMail(core_util_atomic_load_u8(&_currentGear));
}
}
void GearDevice::sendMail(uint32_t data) {
if (_mailBox != nullptr) {
gearMail_t* currentGear = _mailBox->try_alloc();
if (currentGear != nullptr) {
currentGear->gear = data;
currentGear->callTime = _timer.elapsed_time();
_mailBox->put(currentGear);
}
}
}
} // namespace multi_tasking

View File

@ -1,61 +0,0 @@
// 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 gear_device.hpp
* @author Serge Ayer <serge.ayer@hefr.ch>
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Gear Device header file (static scheduling)
*
* @date 2023-11-17
* @version 1.1.0
***************************************************************************/
#pragma once
#include "common/constants.hpp"
#include "mbed.h"
namespace multi_tasking {
typedef struct gearMail {
uint8_t gear;
std::chrono::microseconds callTime;
} gearMail_t;
class GearDevice {
public:
explicit GearDevice(Mail<gearMail_t, 16>* mailBox,
Timer& timer); // NOLINT(runtime/references)
// make the class non copyable
GearDevice(GearDevice&) = delete;
GearDevice& operator=(GearDevice&) = delete;
// method called for updating the bike system
void onUp();
void onDown();
void sendMail(uint32_t data);
private:
// data members
volatile uint8_t _currentGear = bike_computer::kMinGear;
Mail<gearMail_t, 16>* _mailBox;
Timer& _timer;
};
} // namespace multi_tasking

View File

@ -1,85 +0,0 @@
// 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
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Pedal Device implementation (static scheduling)
* @date 2024-11-17
* @version 1.1.0
****************************************************************************/
#include "pedal_device.hpp"
// from disco_h747i/wrappers
#include <chrono>
#include "bike_system.hpp"
#include "joystick.hpp"
#include "mbed_trace.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "PedalDevice"
#endif // MBED_CONF_MBED_TRACE_ENABLE
namespace multi_tasking {
PedalDevice::PedalDevice(Mail<pedalMail_t, 16>* mailBox, Timer& timer)
: _mailBox(mailBox), _timer(timer) {
disco::Joystick::getInstance().setLeftCallback(callback(this, &PedalDevice::onLeft));
disco::Joystick::getInstance().setRightCallback(
callback(this, &PedalDevice::onRight));
}
void PedalDevice::increaseRotationSpeed() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
if (currentStep > 0) {
core_util_atomic_decr_u32(&_currentStep, 1);
sendMail(core_util_atomic_load_u32(&_currentStep));
}
}
void PedalDevice::decreaseRotationSpeed() {
uint32_t currentStep = core_util_atomic_load_u32(&_currentStep);
if (currentStep < bike_computer::kNbrOfSteps) {
core_util_atomic_incr_u32(&_currentStep, 1);
sendMail(core_util_atomic_load_u32(&_currentStep));
}
}
void PedalDevice::onLeft() { decreaseRotationSpeed(); }
void PedalDevice::onRight() { increaseRotationSpeed(); }
void PedalDevice::sendMail(uint32_t data) {
if (_mailBox != nullptr) {
pedalMail_t* currentStep = _mailBox->try_alloc();
if (currentStep != nullptr) {
currentStep->step = data;
currentStep->callTime = _timer.elapsed_time();
_mailBox->put(currentStep);
}
}
}
// static methods
std::chrono::milliseconds PedalDevice::getCurrentRotationTime(uint32_t step) {
return bike_computer::kMinPedalRotationTime +
step * bike_computer::kDeltaPedalRotationTime;
}
} // namespace multi_tasking

View File

@ -1,69 +0,0 @@
// 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.hpp
* @author Serge Ayer <serge.ayer@hefr.ch>
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Pedal System header file (static scheduling)
*
* @date 2023-11-17
* @version 1.1.0
***************************************************************************/
#pragma once
#include "constants.hpp"
#include "mbed.h"
namespace multi_tasking {
typedef struct pedalMail {
uint8_t step;
std::chrono::microseconds callTime;
} pedalMail_t;
class PedalDevice {
public:
explicit PedalDevice(Mail<pedalMail_t, 16>* mailBox, // NOLINT (runtime/references)
Timer& timer); // NOLINT (runtime/references)
// make the class non copyable
PedalDevice(PedalDevice&) = delete;
PedalDevice& operator=(PedalDevice&) = delete;
// method called for updating the bike system
static std::chrono::milliseconds getCurrentRotationTime(uint32_t step);
private:
// private methods
void onLeft();
void onRight();
void increaseRotationSpeed();
void decreaseRotationSpeed();
void sendMail(uint32_t data);
// data members
volatile uint32_t _currentStep = static_cast<uint32_t>(
(bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime)
.count() /
bike_computer::kDeltaPedalRotationTime.count());
Mail<pedalMail_t, 16>* _mailBox;
Timer& _timer;
};
} // namespace multi_tasking

View File

@ -1,48 +0,0 @@
// 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
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief Reset Device implementation (static scheduling with event)
* @date 2024-11-17
* @version 1.1.0
****************************************************************************/
#include "reset_device.hpp"
// from disco_h747i/wrappers
#include <chrono>
#include "joystick.hpp"
#include "mbed_trace.h"
#if defined(TARGET_DISCO_H747I)
#define PUSH_BUTTON BUTTON1
static constexpr uint8_t kPolarityPressed = 1;
#endif
#if MBED_CONF_MBED_TRACE_ENABLE
#define TRACE_GROUP "ResetDevice"
#endif // MBED_CONF_MBED_TRACE_ENABLE
namespace multi_tasking {
ResetDevice::ResetDevice(Callback<void()> cb) : _resetButton(PUSH_BUTTON) {
_resetButton.fall(cb);
}
} // namespace multi_tasking

View File

@ -1,47 +0,0 @@
// 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.hpp
* @author Serge Ayer <serge.ayer@hefr.ch>
* @author Rémi Heredero <remi@heredero.ch>
* @author Yann Sierro <yannsierro.pro@gmail.com>
*
* @brief ResetDevice header file (static scheduling with event)
*
* @date 2023-11-17
* @version 1.1.0
***************************************************************************/
#pragma once
#include "mbed.h"
namespace multi_tasking {
class ResetDevice {
public:
explicit ResetDevice(Callback<void()> cb); // NOLINT(runtime/references)
// make the class non copyable
ResetDevice(ResetDevice&) = delete;
ResetDevice& operator=(ResetDevice&) = delete;
private:
// data members
// instance representing the reset button
InterruptIn _resetButton;
};
} // namespace multi_tasking

View File

@ -0,0 +1,83 @@
#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

@ -0,0 +1,24 @@
#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

@ -61,10 +61,7 @@ BikeSystem::BikeSystem()
: _gearDevice(_timer),
_pedalDevice(_timer),
_resetDevice(_timer),
_displayDevice(),
_speedometer(_timer),
_sensorDevice(),
_taskLogger(),
_cpuLogger(_timer) {}
void BikeSystem::start() {
@ -208,18 +205,29 @@ void BikeSystem::speedDistanceTask() {
_timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime);
}
void BikeSystem::displayTask1() {
void BikeSystem::temperatureTask() {
auto taskStartTime = _timer.elapsed_time();
_displayDevice.displayGear(_currentGear);
_displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance);
tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count());
// no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature();
tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count());
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)));
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
// simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime =
// std::chrono::microseconds::zero(); while (elapsedTime <
// kTemperatureTaskComputationTime) {
// elapsedTime = _timer.elapsed_time() - taskStartTime;
// }
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
}
void BikeSystem::resetTask() {
@ -235,17 +243,27 @@ void BikeSystem::resetTask() {
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime);
}
void BikeSystem::temperatureTask() {
void BikeSystem::displayTask1() {
auto taskStartTime = _timer.elapsed_time();
// no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature();
_displayDevice.displayGear(_currentGear);
_displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)));
// simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime =
// std::chrono::microseconds::zero(); while (elapsedTime <
// kDisplayTask1ComputationTime) {
// elapsedTime = _timer.elapsed_time() - taskStartTime;
// }
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
}
void BikeSystem::displayTask2() {
@ -256,6 +274,13 @@ void BikeSystem::displayTask2() {
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime)));
// simulate task computation by waiting for the required task computation time
// std::chrono::microseconds elapsedTime =
// std::chrono::microseconds::zero(); while (elapsedTime <
// kDisplayTask2ComputationTime) {
// elapsedTime = _timer.elapsed_time() - taskStartTime;
// }
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime);
}

View File

@ -80,7 +80,7 @@ class BikeSystem {
// data member that represents the device for manipulating the gear
GearDevice _gearDevice;
uint8_t _currentGear = bike_computer::kMinGear;
uint8_t _currentGearSize = bike_computer::kMaxGearSize;
uint8_t _currentGearSize = bike_computer::kMinGearSize;
// data member that represents the device for manipulating the pedal rotation
// speed/time
PedalDevice _pedalDevice;

View File

@ -37,7 +37,7 @@ namespace static_scheduling {
static constexpr std::chrono::microseconds kTaskRunTime = 200000us;
PedalDevice::PedalDevice(Timer& timer) : _timer(timer), _pedalRotationTime(0) {}
PedalDevice::PedalDevice(Timer& timer) : _timer(timer) {}
std::chrono::milliseconds PedalDevice::getCurrentRotationTime() {
std::chrono::microseconds initialTime = _timer.elapsed_time();

View File

@ -46,9 +46,9 @@ class PedalDevice {
void decreaseRotationSpeed();
// data members
Timer& _timer;
std::chrono::milliseconds _pedalRotationTime =
bike_computer::kInitialPedalRotationTime;
Timer& _timer;
};
} // namespace static_scheduling

View File

@ -43,8 +43,7 @@ namespace static_scheduling {
static constexpr std::chrono::microseconds kTaskRunTime = 100000us;
ResetDevice::ResetDevice(Timer& timer)
: _resetButton(PUSH_BUTTON), _timer(timer), _pressTime(0) {
ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) {
_resetButton.rise(callback(this, &ResetDevice::onRise));
}

View File

@ -67,10 +67,7 @@ BikeSystem::BikeSystem()
: _gearDevice(),
_pedalDevice(),
_resetDevice(callback(this, &BikeSystem::onReset)),
_displayDevice(),
_speedometer(_timer),
_sensorDevice(),
_taskLogger(),
_cpuLogger(_timer) {}
void BikeSystem::start() {
@ -179,18 +176,21 @@ void BikeSystem::speedDistanceTask() {
_timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime);
}
void BikeSystem::displayTask1() {
void BikeSystem::temperatureTask() {
auto taskStartTime = _timer.elapsed_time();
_displayDevice.displayGear(_currentGear);
_displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance);
// tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count());
// no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature();
// tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count());
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)));
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
}
void BikeSystem::resetTask() {
@ -208,17 +208,18 @@ void BikeSystem::resetTask() {
_timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime);
}
void BikeSystem::temperatureTask() {
void BikeSystem::displayTask1() {
auto taskStartTime = _timer.elapsed_time();
// no need to protect access to data members (single threaded)
_currentTemperature = _sensorDevice.readTemperature();
_displayDevice.displayGear(_currentGear);
_displayDevice.displaySpeed(_currentSpeed);
_displayDevice.displayDistance(_traveledDistance);
ThisThread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(
kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime)));
kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime)));
_taskLogger.logPeriodAndExecutionTime(
_timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime);
_timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime);
}
void BikeSystem::displayTask2() {

View File

@ -85,7 +85,7 @@ class BikeSystem {
// data member that represents the device for manipulating the gear
GearDevice _gearDevice;
uint8_t _currentGear = bike_computer::kMinGear;
uint8_t _currentGearSize = bike_computer::kMaxGearSize;
uint8_t _currentGearSize = bike_computer::kMinGearSize;
// data member that represents the device for manipulating the pedal rotation
// speed/time
PedalDevice _pedalDevice;

1
update-client.lib Normal file
View File

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