From 86ccb3ca172624662bfa2efd3b5d65ba3aa336a1 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 22 Oct 2024 15:37:47 +0200 Subject: [PATCH 01/30] ADD libraries for disco board and extarnal sensor --- .gitignore | 2 ++ DISCO_H747I.lib | 1 + advdembsof_library.lib | 1 + 3 files changed, 4 insertions(+) create mode 100644 DISCO_H747I.lib create mode 100644 advdembsof_library.lib diff --git a/.gitignore b/.gitignore index 9e90278..ab749f6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ projectfiles *.py* BUILD mbed-os +DISCO_h747i +advdembsof_library diff --git a/DISCO_H747I.lib b/DISCO_H747I.lib new file mode 100644 index 0000000..02ddf99 --- /dev/null +++ b/DISCO_H747I.lib @@ -0,0 +1 @@ +https://github.com/SergeAyer/DISCO_H747I/#2b367efbbf0d66205403647c0d0227808d0529ed diff --git a/advdembsof_library.lib b/advdembsof_library.lib new file mode 100644 index 0000000..e2720e9 --- /dev/null +++ b/advdembsof_library.lib @@ -0,0 +1 @@ +https://github.com/SergeAyer/advdembsof_library/#c0687fc795de83780fa9e7e935c9f465d697cc2a From f8ff28aef647e718b4d7256dc853c4fcb3d0331e Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 22 Oct 2024 15:44:41 +0200 Subject: [PATCH 02/30] UDP README.md for additional libraries and test --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index c8e088d..2620e81 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,20 @@ AdvEmbSoft/HESSO-Master/2024 # BikeComputer This is a project done in the course of AdvEmbSoft during the master's degree. It contains a program for spinning bikes. +# Configuration +## Libraries +Add disco libraries : +´´´terminal +mbed add https://github.com/SergeAyer/DISCO_H747I.git +´´´ +Add sensor libraries : + +´´´terminal +mbed add https://github.com/SergeAyer/advdembsof_library.git +´´´ + +Test sensor libraries : +´´´terminal +mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run +´´´ From 5ef0203a27e8e3e509560e841464af17407a144a Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 22 Oct 2024 15:48:08 +0200 Subject: [PATCH 03/30] UPD README.md for wrong symbol to illustrate commands --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2620e81..73349c5 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,16 @@ This is a project done in the course of AdvEmbSoft during the master's degree. I ## Libraries Add disco libraries : -´´´terminal +```terminal mbed add https://github.com/SergeAyer/DISCO_H747I.git -´´´ +``` Add sensor libraries : -´´´terminal +```terminal mbed add https://github.com/SergeAyer/advdembsof_library.git -´´´ +``` Test sensor libraries : -´´´terminal +```terminal mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run -´´´ +``` From 0634d16ba3b38acbcd61197554ea77cbea862ab1 Mon Sep 17 00:00:00 2001 From: fastium Date: Wed, 23 Oct 2024 08:54:27 +0200 Subject: [PATCH 04/30] UPD test for github action (sensor) --- .github/workflows/build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index dd89ccd..56b70af 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -18,7 +18,8 @@ jobs: tests-simple-test-always-succeed, tests-simple-test-ptr-test, tests-simple-unique-ptr, - tests-simple-test-raw-ptr + tests-simple-test-raw-ptr, + advdembsof_library-tests-sensors-hdc1000 ] From b1d04badfbec5ba765e8f927940f580579ebe510 Mon Sep 17 00:00:00 2001 From: fastium Date: Wed, 23 Oct 2024 10:59:38 +0200 Subject: [PATCH 05/30] ADD sensor device classes --- common/constants.hpp | 54 ++++++++++++++++++++++++++++++++++++++++ common/sensor_device.cpp | 21 ++++++++++++++++ common/sensor_device.hpp | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 common/constants.hpp create mode 100644 common/sensor_device.cpp create mode 100644 common/sensor_device.hpp diff --git a/common/constants.hpp b/common/constants.hpp new file mode 100644 index 0000000..8774f8f --- /dev/null +++ b/common/constants.hpp @@ -0,0 +1,54 @@ +// 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 constants.hpp + * @author Serge Ayer + * + * @brief Constants definition used for implementing the bike system + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include + +#include "mbed.h" + +namespace bike_computer { + +// gear related constants +static constexpr uint8_t kMinGear = 1; +static constexpr uint8_t kMaxGear = 9; +// smallest gear (= 1) corresponds to a gear size of 20 +// when the gear increases, the gear size descreases +static constexpr uint8_t kMaxGearSize = 20; +static constexpr uint8_t kMinGearSize = kMaxGearSize - kMaxGear; + +// pedal related constants +// When compiling and linking with gcc, we get a link error when using static +// constexpr. The error is related to template instantiation. + +// definition of pedal rotation initial time (corresponds to 80 turn / min) +static constexpr std::chrono::milliseconds kInitialPedalRotationTime = 750ms; +// definition of pedal minimal rotation time (corresponds to 160 turn / min) +static constexpr std::chrono::milliseconds kMinPedalRotationTime = 375ms; +// definition of pedal maximal rotation time (corresponds to 10 turn / min) +static constexpr std::chrono::milliseconds kMaxPedalRotationTime = 1500ms; +// definition of pedal rotation time change upon acceleration/deceleration +static constexpr std::chrono::milliseconds kDeltaPedalRotationTime = 25ms; + +} // namespace bike_computer \ No newline at end of file diff --git a/common/sensor_device.cpp b/common/sensor_device.cpp new file mode 100644 index 0000000..4aa7ef2 --- /dev/null +++ b/common/sensor_device.cpp @@ -0,0 +1,21 @@ +#include "sensor_device.hpp" + +namespace bike_computer { + +SensorDevice::SensorDevice() : _hdc1000(I2C_SDA, I2C_SCL, STMOD_11) +{} + +bool SensorDevice::init() { + return this->_hdc1000.probe(); +} + +float SensorDevice::readTemperature(void) { + return this->_hdc1000.getTemperature(); +} + +float SensorDevice::readHumidity(void) { + return this->_hdc1000.getHumidity(); +} + +} // bike_computer + diff --git a/common/sensor_device.hpp b/common/sensor_device.hpp new file mode 100644 index 0000000..d6ead2c --- /dev/null +++ b/common/sensor_device.hpp @@ -0,0 +1,49 @@ +// 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 sensor_device.hpp + * @author Serge Ayer + * + * @brief SensorDevice header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "hdc1000.hpp" +#include "mbed.h" + +namespace bike_computer { + +class SensorDevice { + public: + // constructor + SensorDevice(); + + // method for initializing the device + bool init(); + + // methods used for + float readTemperature(void); + float readHumidity(void); + + private: + // data members + advembsof::HDC1000 _hdc1000; +}; + +} // namespace bike_computer \ No newline at end of file From b9fda1aefe5185f2ca56cc4e025c70a029f18775 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 29 Oct 2024 16:13:20 +0100 Subject: [PATCH 06/30] ADD Tests for the sensor --- .github/workflows/build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 56b70af..3db23d2 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -19,7 +19,8 @@ jobs: tests-simple-test-ptr-test, tests-simple-unique-ptr, tests-simple-test-raw-ptr, - advdembsof_library-tests-sensors-hdc1000 + advdembsof_library-tests-sensors-hdc1000, + tests-bike-computer-sensor-device ] From 0d4e603a647ab171a7e8524a8918351f557d00b6 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 29 Oct 2024 16:15:32 +0100 Subject: [PATCH 07/30] ADD speedometer and gear class --- common/speedometer.cpp | 125 ++++++++++++++++++++++++++++++ common/speedometer.hpp | 91 ++++++++++++++++++++++ static_scheduling/gear_device.cpp | 83 ++++++++++++++++++++ static_scheduling/gear_device.hpp | 50 ++++++++++++ 4 files changed, 349 insertions(+) create mode 100644 common/speedometer.cpp create mode 100644 common/speedometer.hpp create mode 100644 static_scheduling/gear_device.cpp create mode 100644 static_scheduling/gear_device.hpp diff --git a/common/speedometer.cpp b/common/speedometer.cpp new file mode 100644 index 0000000..a30ecaa --- /dev/null +++ b/common/speedometer.cpp @@ -0,0 +1,125 @@ +// 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 + * + * @brief WheelCounterDevice implementation (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#include "speedometer.hpp" + +#include +#include + +// from disco_h747i/wrappers +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "Speedometer" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace bike_computer { + +Speedometer::Speedometer(Timer& timer) : _timer(timer) { + // update _lastTime + _lastTime = _timer.elapsed_time(); +} + +void Speedometer::setCurrentRotationTime( + const std::chrono::milliseconds& currentRotationTime) { + if (_pedalRotationTime != currentRotationTime) { + // compute distance before changing the rotation time + computeDistance(); + + // change pedal rotation time + _pedalRotationTime = currentRotationTime; + + // compute speed with the new pedal rotation time + computeSpeed(); + } +} + +void Speedometer::setGearSize(uint8_t gearSize) { + if (_gearSize != gearSize) { + // compute distance before chaning the gear size + computeDistance(); + + // change gear size + _gearSize = gearSize; + + // compute speed with the new gear size + computeSpeed(); + } +} + +float Speedometer::getCurrentSpeed() const { return _currentSpeed; } + +float Speedometer::getDistance() { + // make sure to update the distance traveled + computeDistance(); + return _totalDistance; +} + +void Speedometer::reset() { + // TODO : done + this->_totalDistanceMutex.lock(); + this->_totalDistance = 0.0f; + this->_totalDistanceMutex.unlock(); +} + +#if defined(MBED_TEST_MODE) +uint8_t Speedometer::getGearSize() const { return _gearSize; } + +float Speedometer::getWheelCircumference() const { return kWheelCircumference; } + +float Speedometer::getTraySize() const { return kTraySize; } + +std::chrono::milliseconds Speedometer::getCurrentPedalRotationTime() const { + return _pedalRotationTime; +} + +#endif // defined(MBED_TEST_MODE) + +void Speedometer::computeSpeed() { + // For computing the speed given a rear gear (braquet), one must divide the size of + // the tray (plateau) by the size of the rear gear (pignon arrière), and then multiply + // the result by the circumference of the wheel. Example: tray = 50, rear gear = 15. + // Distance run with one pedal turn (wheel circumference = 2.10 m) = 50/15 * 2.1 m + // = 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 + + // TODO + + +} + +void Speedometer::computeDistance() { + // For computing the speed given a rear gear (braquet), one must divide the size of + // the tray (plateau) by the size of the rear gear (pignon arrière), and then multiply + // the result by the circumference of the wheel. Example: tray = 50, rear gear = 15. + // Distance run with one pedal turn (wheel circumference = 2.10 m) = 50/15 * 2.1 m + // = 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. We then multiply the speed by the time for getting the + // distance traveled. + + // TODO +} + +} // namespace bike_computer \ No newline at end of file diff --git a/common/speedometer.hpp b/common/speedometer.hpp new file mode 100644 index 0000000..bbc1e6b --- /dev/null +++ b/common/speedometer.hpp @@ -0,0 +1,91 @@ +// 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.hpp + * @author Serge Ayer + * + * @brief WheelCounterDevice header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace bike_computer { + +class Speedometer { + public: + explicit Speedometer(Timer& timer); // NOLINT(runtime/references) + + // method used for setting the current pedal rotation time + void setCurrentRotationTime(const std::chrono::milliseconds& currentRotationTime); + + // method used for setting/getting the current gear + void setGearSize(uint8_t gearSize); + + // method called for getting the current speed (expressed in km / h) + float getCurrentSpeed() const; + + // method called for getting the current traveled distance (expressed in km) + float getDistance(); + + // method called for resetting the traveled distance + void reset(); + + // methods used for tests only +#if defined(MBED_TEST_MODE) + uint8_t getGearSize() const; + float getWheelCircumference() const; + float getTraySize() const; + std::chrono::milliseconds getCurrentPedalRotationTime() const; + void setOnResetCallback(mbed::Callback cb); +#endif // defined(MBED_TEST_MODE) + + private: + // private methods + void computeSpeed(); + void computeDistance(); + + // definition of task period time + static constexpr std::chrono::milliseconds kTaskPeriod = 400ms; + // definition of task execution time + static constexpr std::chrono::microseconds kTaskRunTime = 200000us; + + // constants related to speed computation + static constexpr float kWheelCircumference = 2.1f; + static constexpr uint8_t kTraySize = 50; + std::chrono::microseconds _lastTime = std::chrono::microseconds::zero(); + std::chrono::milliseconds _pedalRotationTime = kInitialPedalRotationTime; + + // data members + Timer& _timer; + LowPowerTicker _ticker; + float _currentSpeed = 0.0f; + Mutex _totalDistanceMutex; + float _totalDistance = 0.0f; + uint8_t _gearSize = 1; + + Thread _thread; + +#if defined(MBED_TEST_MODE) + mbed::Callback _cb; +#endif +}; + +} // namespace bike_computer \ No newline at end of file diff --git a/static_scheduling/gear_device.cpp b/static_scheduling/gear_device.cpp new file mode 100644 index 0000000..e120ce2 --- /dev/null +++ b/static_scheduling/gear_device.cpp @@ -0,0 +1,83 @@ +// 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 + * + * @brief Gear Device implementation (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#include "gear_device.hpp" + +// from disco_h747i/wrappers +#include + +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "GearDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling { + +// definition of task execution time +static constexpr std::chrono::microseconds kTaskRunTime = 100000us; + +GearDevice::GearDevice(Timer& timer) : _timer(timer) {} + +uint8_t GearDevice::getCurrentGear() { + 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) { + case disco::Joystick::State::UpPressed: + if (_currentGear < bike_computer::kMaxGear) { + _currentGear++; + } + hasChanged = true; + break; + + case disco::Joystick::State::DownPressed: + if (_currentGear > bike_computer::kMinGear) { + _currentGear--; + } + hasChanged = true; + break; + + default: + break; + } + } + elapsedTime = _timer.elapsed_time() - initialTime; + } + return _currentGear; +} + +uint8_t GearDevice::getCurrentGearSize() const { + // simulate task computation by waiting for the required task run time + // wait_us(kTaskRunTime.count()); + return bike_computer::kMaxGearSize - _currentGear; +} + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling/gear_device.hpp b/static_scheduling/gear_device.hpp new file mode 100644 index 0000000..d44d6f7 --- /dev/null +++ b/static_scheduling/gear_device.hpp @@ -0,0 +1,50 @@ +// 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 + * + * @brief Gear Device header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace static_scheduling { + +class GearDevice { + public: + explicit GearDevice(Timer& timer); // NOLINT(runtime/references) + + // make the class non copyable + GearDevice(GearDevice&) = delete; + GearDevice& operator=(GearDevice&) = delete; + + // method called for updating the bike system + uint8_t getCurrentGear(); + uint8_t getCurrentGearSize() const; + + private: + // data members + uint8_t _currentGear = bike_computer::kMinGear; + Timer& _timer; +}; + +} // namespace static_scheduling \ No newline at end of file From db2d5308bc14cd5ea7e40cb0d1cd071d5f46ea32 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 29 Oct 2024 16:16:30 +0100 Subject: [PATCH 08/30] ADD tests for speedometer and sensor-device --- TESTS/bike-computer/sensor-device/main.cpp | 69 ++++ TESTS/bike-computer/speedometer/main.cpp | 354 +++++++++++++++++++++ 2 files changed, 423 insertions(+) create mode 100644 TESTS/bike-computer/sensor-device/main.cpp create mode 100644 TESTS/bike-computer/speedometer/main.cpp diff --git a/TESTS/bike-computer/sensor-device/main.cpp b/TESTS/bike-computer/sensor-device/main.cpp new file mode 100644 index 0000000..9792526 --- /dev/null +++ b/TESTS/bike-computer/sensor-device/main.cpp @@ -0,0 +1,69 @@ +// 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 main.cpp + * @author Serge Ayer + * + * @brief Bike computer test suite: sensor device + * + * @date 2023-08-26 + * @version 0.1.0 + ***************************************************************************/ + +#include "greentea-client/test_env.h" +#include "hdc1000.hpp" +#include "mbed.h" +#include "sensor_device.hpp" +#include "unity/unity.h" +#include "utest/utest.h" + +using namespace utest::v1; + +// test_hdc1000 test handler function +static control_t test_sensor_device(const size_t call_count) { + // create the SensorDevice instance + bike_computer::SensorDevice sensorDevice; + + bool rc = sensorDevice.init(); + TEST_ASSERT_TRUE(rc); + + float temperature = sensorDevice.readTemperature(); + static constexpr float kTemperatureRange = 20.0f; + static constexpr float kMeanTemperature = 15.0f; + TEST_ASSERT_FLOAT_WITHIN(kTemperatureRange, kMeanTemperature, temperature); + + float humidity = sensorDevice.readHumidity(); + static constexpr float kHumidityRange = 40.0f; + static constexpr float kMeanHumidity = 50.0f; + TEST_ASSERT_FLOAT_WITHIN(kHumidityRange, kMeanHumidity, humidity); + + // execute the test only once and move to the next one, without waiting + return CaseNext; +} + +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 or the + // name of our Python file) + GREENTEA_SETUP(60, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +// List of test cases in this file +static Case cases[] = {Case("test sensor device", test_sensor_device)}; + +static Specification specification(greentea_setup, cases); + +int main() { return !Harness::run(specification); } \ No newline at end of file diff --git a/TESTS/bike-computer/speedometer/main.cpp b/TESTS/bike-computer/speedometer/main.cpp new file mode 100644 index 0000000..26a2906 --- /dev/null +++ b/TESTS/bike-computer/speedometer/main.cpp @@ -0,0 +1,354 @@ +// 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 main.cpp + * @author Serge Ayer + * + * @brief Bike computer test suite: speedometer device + * + * @date 2023-08-26 + * @version 0.1.0 + ***************************************************************************/ + +#include + +#include "common/constants.hpp" +#include "common/speedometer.hpp" +#include "greentea-client/test_env.h" +#include "mbed.h" +#include "static_scheduling/gear_device.hpp" +#include "unity/unity.h" +#include "utest/utest.h" + +using namespace utest::v1; + +// allow for 0.1 km/h difference +static constexpr float kAllowedSpeedDelta = 0.1f; +// allow for 1m difference +static constexpr float kAllowedDistanceDelta = 1.0f / 1000.0; + +// function called by test handler functions for verifying the current speed +void check_current_speed(const std::chrono::milliseconds& pedalRotationTime, + uint8_t traySize, + uint8_t gearSize, + float wheelCircumference, + float currentSpeed) { + // compute the number of pedal rotation per hour + uint32_t milliSecondsPerHour = 1000 * 3600; + float pedalRotationsPerHour = static_cast(milliSecondsPerHour) / + static_cast(pedalRotationTime.count()); + + // compute the expected speed in km / h + // first compute the distance in meter for each pedal turn + float trayGearRatio = static_cast(traySize) / static_cast(gearSize); + float distancePerPedalTurn = trayGearRatio * wheelCircumference; + float expectedSpeed = (distancePerPedalTurn / 1000.0f) * pedalRotationsPerHour; + + printf(" Expected speed is %f, current speed is %f\n", expectedSpeed, currentSpeed); + TEST_ASSERT_FLOAT_WITHIN(kAllowedSpeedDelta, expectedSpeed, currentSpeed); +} + +// compute the traveled distance for a time interval +float compute_distance(const std::chrono::milliseconds& pedalRotationTime, + uint8_t traySize, + uint8_t gearSize, + float wheelCircumference, + const std::chrono::milliseconds& travelTime) { + // compute the number of pedal rotation during travel time + // both times are expressed in ms + float pedalRotations = static_cast(travelTime.count()) / + static_cast(pedalRotationTime.count()); + + // compute the distance in meter for each pedal turn + float trayGearRatio = static_cast(traySize) / static_cast(gearSize); + float distancePerPedalTurn = trayGearRatio * wheelCircumference; + + // distancePerPedalTurn is expressed in m, divide per 1000 for a distance in km + return (distancePerPedalTurn * pedalRotations) / 1000.0; +} + +// function called by test handler functions for verifying the distance traveled +void check_distance(const std::chrono::milliseconds& pedalRotationTime, + uint8_t traySize, + uint8_t gearSize, + float wheelCircumference, + const std::chrono::milliseconds& travelTime, + float distance) { + // distancePerPedalTurn is expressed in m, divide per 1000 for a distance in km + float expectedDistance = compute_distance( + pedalRotationTime, traySize, gearSize, wheelCircumference, travelTime); + printf(" Expected distance is %f, current distance is %f\n", + expectedDistance, + distance); + TEST_ASSERT_FLOAT_WITHIN(kAllowedDistanceDelta, expectedDistance, distance); +} + +// test the speedometer by modifying the gear +static control_t test_gear_size(const size_t call_count) { + // create a timer + Timer timer; + // start the timer + timer.start(); + + // create a speedometer instance + bike_computer::Speedometer speedometer(timer); + + // get speedometer constant values (for this test) + const auto traySize = speedometer.getTraySize(); + const auto wheelCircumference = speedometer.getWheelCircumference(); + const auto pedalRotationTime = speedometer.getCurrentPedalRotationTime(); + + for (uint8_t gearSize = bike_computer::kMinGearSize; + gearSize <= bike_computer::kMaxGearSize; + gearSize++) { + // set the gear + printf("Testing gear size %d\n", gearSize); + speedometer.setGearSize(gearSize); + + // get the current speed + auto currentSpeed = speedometer.getCurrentSpeed(); + + // check the speed against the expected one + check_current_speed( + pedalRotationTime, traySize, gearSize, wheelCircumference, currentSpeed); + } + + // execute the test only once and move to the next one, without waiting + return CaseNext; +} + +// test the speedometer by modifying the pedal rotation speed +static control_t test_rotation_speed(const size_t call_count) { + // create a timer + Timer timer; + // start the timer + timer.start(); + + // create a speedometer instance + bike_computer::Speedometer speedometer(timer); + + // set the gear size + speedometer.setGearSize(bike_computer::kMaxGearSize); + + // get speedometer constant values + const auto traySize = speedometer.getTraySize(); + const auto wheelCircumference = speedometer.getWheelCircumference(); + const auto gearSize = speedometer.getGearSize(); + + // first test increasing rotation speed (decreasing rotation time) + auto pedalRotationTime = speedometer.getCurrentPedalRotationTime(); + while (pedalRotationTime > bike_computer::kMinPedalRotationTime) { + // decrease the pedal rotation time + pedalRotationTime -= bike_computer::kDeltaPedalRotationTime; + speedometer.setCurrentRotationTime(pedalRotationTime); + + // get the current speed + const auto currentSpeed = speedometer.getCurrentSpeed(); + + // check the speed against the expected one + check_current_speed( + pedalRotationTime, traySize, gearSize, wheelCircumference, currentSpeed); + } + + // second test decreasing rotation speed (increasing rotation time) + pedalRotationTime = speedometer.getCurrentPedalRotationTime(); + while (pedalRotationTime < bike_computer::kMaxPedalRotationTime) { + // increase the pedal rotation time + pedalRotationTime += bike_computer::kDeltaPedalRotationTime; + speedometer.setCurrentRotationTime(pedalRotationTime); + + // get the current speed + const auto currentSpeed = speedometer.getCurrentSpeed(); + + // check the speed against the expected one + check_current_speed( + pedalRotationTime, traySize, gearSize, wheelCircumference, currentSpeed); + } + + // execute the test only once and move to the next one, without waiting + return CaseNext; +} + +// test the speedometer by modifying the pedal rotation speed +static control_t test_distance(const size_t call_count) { + // create a timer + Timer timer; + + // create a speedometer instance + bike_computer::Speedometer speedometer(timer); + + // set the gear size + speedometer.setGearSize(bike_computer::kMaxGearSize); + + // get speedometer constant values + const auto traySize = speedometer.getTraySize(); + const auto wheelCircumference = speedometer.getWheelCircumference(); + auto gearSize = speedometer.getGearSize(); + auto pedalRotationTime = speedometer.getCurrentPedalRotationTime(); + + // test different travel times + const std::chrono::milliseconds travelTimes[] = {500ms, 1000ms, 5s, 10s}; + const uint8_t nbrOfTravelTimes = sizeof(travelTimes) / sizeof(travelTimes[0]); + + // start the timer (for simulating bike start) + timer.start(); + + // first check travel distance without changing gear and rotation speed + std::chrono::milliseconds totalTravelTime = std::chrono::milliseconds::zero(); + for (uint8_t index = 0; index < nbrOfTravelTimes; index++) { + // run for the travel time and get the distance + ThisThread::sleep_for(travelTimes[index]); + + // get the distance traveled + const auto distance = speedometer.getDistance(); + + // accumulate travel time + totalTravelTime += travelTimes[index]; + + // check the distance vs the expected one + check_distance(pedalRotationTime, + traySize, + gearSize, + wheelCircumference, + totalTravelTime, + distance); + } + + // now change gear at each time interval + auto expectedDistance = speedometer.getDistance(); + for (uint8_t index = 0; index < nbrOfTravelTimes; index++) { + // update the gear size + gearSize++; + speedometer.setGearSize(gearSize); + + // run for the travel time and get the distance + ThisThread::sleep_for(travelTimes[index]); + + // compute the expected distance for this time segment + float distance = compute_distance(pedalRotationTime, + traySize, + gearSize, + wheelCircumference, + travelTimes[index]); + expectedDistance += distance; + + // get the distance traveled + const auto traveledDistance = speedometer.getDistance(); + + printf(" Expected distance is %f, current distance is %f\n", + expectedDistance, + traveledDistance); + TEST_ASSERT_FLOAT_WITHIN( + kAllowedDistanceDelta, expectedDistance, traveledDistance); + } + // now change rotation speed at each time interval + expectedDistance = speedometer.getDistance(); + for (uint8_t index = 0; index < nbrOfTravelTimes; index++) { + // update the rotation speed + pedalRotationTime += bike_computer::kDeltaPedalRotationTime; + speedometer.setCurrentRotationTime(pedalRotationTime); + + // run for the travel time and get the distance + ThisThread::sleep_for(travelTimes[index]); + + // compute the expected distance for this time segment + float distance = compute_distance(pedalRotationTime, + traySize, + gearSize, + wheelCircumference, + travelTimes[index]); + expectedDistance += distance; + + // get the distance traveled + const auto traveledDistance = speedometer.getDistance(); + + printf(" Expected distance is %f, current distance is %f\n", + expectedDistance, + traveledDistance); + TEST_ASSERT_FLOAT_WITHIN( + kAllowedDistanceDelta, expectedDistance, traveledDistance); + } + + // execute the test only once and move to the next one, without waiting + return CaseNext; +} + +// test the speedometer by modifying the pedal rotation speed +static control_t test_reset(const size_t call_count) { + // create a timer instance + Timer timer; + + // create a speedometer instance + bike_computer::Speedometer speedometer(timer); + + // set the gear size + speedometer.setGearSize(bike_computer::kMinGearSize); + + // get speedometer constant values + const auto traySize = speedometer.getTraySize(); + const auto wheelCircumference = speedometer.getWheelCircumference(); + const auto gearSize = speedometer.getGearSize(); + const auto pedalRotationTime = speedometer.getCurrentPedalRotationTime(); + + // start the timer (for simulating bike start) + timer.start(); + + // travel for 1 second + const auto travelTime = 1000ms; + ThisThread::sleep_for(travelTime); + + // check the expected distaance traveled + const auto expectedDistance = compute_distance( + pedalRotationTime, traySize, gearSize, wheelCircumference, travelTime); + + // get the distance traveled + auto traveledDistance = speedometer.getDistance(); + + printf(" Expected distance is %f, current distance is %f\n", + expectedDistance, + traveledDistance); + TEST_ASSERT_FLOAT_WITHIN(kAllowedDistanceDelta, expectedDistance, traveledDistance); + + // reset the speedometer + speedometer.reset(); + + // traveled distance should now be zero + traveledDistance = speedometer.getDistance(); + + printf(" Expected distance is %f, current distance is %f\n", 0.0f, traveledDistance); + TEST_ASSERT_FLOAT_WITHIN(kAllowedDistanceDelta, 0.0f, traveledDistance); + + // execute the test only once and move to the next one, without waiting + return CaseNext; +} + +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 or the + // name of our Python file) + GREENTEA_SETUP(180, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +// List of test cases in this file +static Case cases[] = { + Case("test speedometer gear size change", test_gear_size), + Case("test speedometer rotation speed change", test_rotation_speed), + Case("test speedometer distance", test_distance), + Case("test speedometer reset", test_reset)}; + +static Specification specification(greentea_setup, cases); + +int main() { return !Harness::run(specification); } \ No newline at end of file From 0d18073562267ee0f13bfe9a3658698858e77855 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 29 Oct 2024 17:10:58 +0100 Subject: [PATCH 09/30] ADD (WIP) speedometer implementation --- common/speedometer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/speedometer.cpp b/common/speedometer.cpp index a30ecaa..7f1b4c1 100644 --- a/common/speedometer.cpp +++ b/common/speedometer.cpp @@ -24,6 +24,8 @@ #include "speedometer.hpp" +#include "static_scheduling/gear_device.hpp" + #include #include @@ -106,8 +108,9 @@ void Speedometer::computeSpeed() { // ~= 560 m / min = 33.6 km/h // TODO - - + //Distance run with one pedal turn = tray size / rear gear size * circumference of the wheel + std::chrono::seconds pedal_rotation_time = std::chrono::duration_cast(this->_pedalRotationTime).count(); + this->_currentSpeed = static_cast(kTraySize) / this->_gearSize * this->kWheelCircumference * ; } void Speedometer::computeDistance() { @@ -120,6 +123,7 @@ void Speedometer::computeDistance() { // distance traveled. // TODO + } } // namespace bike_computer \ No newline at end of file From ac8e030089c557acbdbe0d10d53662ca8950b24e Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 5 Nov 2024 15:30:12 +0100 Subject: [PATCH 10/30] ADD speedometer implementation --- common/speedometer.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/common/speedometer.cpp b/common/speedometer.cpp index 7f1b4c1..19ba566 100644 --- a/common/speedometer.cpp +++ b/common/speedometer.cpp @@ -107,10 +107,13 @@ 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 - // TODO + // TODO : done //Distance run with one pedal turn = tray size / rear gear size * circumference of the wheel - std::chrono::seconds pedal_rotation_time = std::chrono::duration_cast(this->_pedalRotationTime).count(); - this->_currentSpeed = static_cast(kTraySize) / this->_gearSize * this->kWheelCircumference * ; + float ms_in_hour = static_cast(3600 * 1000); + float pedal_rotation_per_hour = ms_in_hour / static_cast(_pedalRotationTime.count()); + float gear_ratio = static_cast(kTraySize) / static_cast(this->_gearSize); + float wheel_dist_km = static_cast(this->kWheelCircumference) / 1000.0; + this->_currentSpeed = gear_ratio * wheel_dist_km * pedal_rotation_per_hour; } void Speedometer::computeDistance() { @@ -122,8 +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 - + // TODO : done + Speedometer::computeSpeed(); + // compute distance + float last_time_in_hour = static_cast(std::chrono::duration_cast(this->_lastTime).count()); + float traveled_dist = this->_currentSpeed * last_time_in_hour; + this->_totalDistanceMutex.lock(); + this->_totalDistance += traveled_dist; + this->_totalDistanceMutex.unlock(); } } // namespace bike_computer \ No newline at end of file From dc99ac08b5cd6609087f791336cd7f3175e6f59c Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 5 Nov 2024 16:21:51 +0100 Subject: [PATCH 11/30] ADD speedometer tests in CI for github --- .github/workflows/build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3db23d2..e2c92a3 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,7 +20,8 @@ jobs: tests-simple-unique-ptr, tests-simple-test-raw-ptr, advdembsof_library-tests-sensors-hdc1000, - tests-bike-computer-sensor-device + tests-bike-computer-sensor-device, + tests-bike-computer-speedometer ] From 43cacadfb74e477dee6d926a32a4b47fab1323ff Mon Sep 17 00:00:00 2001 From: Klagarge Date: Tue, 5 Nov 2024 16:51:21 +0100 Subject: [PATCH 12/30] FIX conflict when merge main to develop --- .github/workflows/build-test.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e2c92a3..525f524 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -13,12 +13,10 @@ jobs: strategy: matrix: target: [DISCO_H747I] - profile: [develop, debug, release] + profile: [debug, release] tests: [ tests-simple-test-always-succeed, tests-simple-test-ptr-test, - tests-simple-unique-ptr, - tests-simple-test-raw-ptr, advdembsof_library-tests-sensors-hdc1000, tests-bike-computer-sensor-device, tests-bike-computer-speedometer From af0b6180da8fedc85eec458a9602b62b3b6abd7c Mon Sep 17 00:00:00 2001 From: Klagarge Date: Wed, 6 Nov 2024 12:35:04 +0100 Subject: [PATCH 13/30] FIX raw + unique ptr tests (#12) FIX issues on raw and unique pointer tests + Merge individual test files for unique and raw pointers and merged their test cases into a single test file for simplicity. Co-authored-by: Fastium <79766552+Fastium@users.noreply.github.com> --- TESTS/simple-test/test-ptr/main.cpp | 183 ++++++++++++++++++++++- TESTS/simple-test/test-raw-ptr/main.cpp | 96 ------------ TESTS/simple-test/unique-ptr/main.cpp | 189 ------------------------ 3 files changed, 180 insertions(+), 288 deletions(-) delete mode 100644 TESTS/simple-test/test-raw-ptr/main.cpp delete mode 100644 TESTS/simple-test/unique-ptr/main.cpp diff --git a/TESTS/simple-test/test-ptr/main.cpp b/TESTS/simple-test/test-ptr/main.cpp index 142846d..7314532 100644 --- a/TESTS/simple-test/test-ptr/main.cpp +++ b/TESTS/simple-test/test-ptr/main.cpp @@ -15,11 +15,13 @@ /**************************************************************************** * @file main.cpp * @author Serge Ayer + * @author Yann Sierro + * @author Rémi Heredero * * @brief Simple example of test program for raw and shared pointers * - * @date 2022-09-01 - * @version 0.1.0 + * @date 2024-11-02 + * @version 0.2.0 ***************************************************************************/ #include "greentea-client/test_env.h" @@ -94,6 +96,170 @@ void test_instance_sharing() { TEST_ASSERT_EQUAL(0, Test::_instanceCount); } +/********************** +* UNIQUE PTR EXERCISE * +**********************/ + +/* + * Check normal lifetime on a unique_ptr + */ +void test_single_unique_ptr_lifetime() { + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + + // create and destroy a unique_ptr + { + std::unique_ptr p1 = std::make_unique(); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); + + const uint32_t number = 42; + p1->_value = number; + TEST_ASSERT_EQUAL(number, p1->_value); + + p1.reset(); + TEST_ASSERT(!p1); + } + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); +} + +/* + * Check transfer on a unique_ptr + */ +void test_unique_ptr_transfer() { + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + + { + //create p1 + std::unique_ptr p1 = std::make_unique(); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + + //transfer p1 to p2 + std::unique_ptr p2 = std::move(p1); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + + p2.reset(); + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + TEST_ASSERT(!p1); + TEST_ASSERT(!p2); + } + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); +} + +/* + * Check the release of a unique ptr + */ +void test_unique_ptr_release() { + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + + { + //create p1 + std::unique_ptr p1 = std::make_unique(); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + + //transfer and release p1 to p2 + Test * p2 = p1.release(); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + + delete p2; + p2 = nullptr; + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + TEST_ASSERT(!p1); + TEST_ASSERT(!p2); + } + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); +} + +/* + * Check the swap of 2 unique ptr + */ +void test_unique_ptr_swap() { + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + + { + const uint32_t number1 = 65; + const uint32_t number2 = 42; + + //create p1 + std::unique_ptr p1 = std::make_unique(); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + p1->_value = number1; + TEST_ASSERT_EQUAL(number1, p1->_value); + + //create p2 + std::unique_ptr p2 = std::make_unique(); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); + TEST_ASSERT_EQUAL(2, Test::_instanceCount); + p2->_value = number2; + TEST_ASSERT_EQUAL(number2, p2->_value); + + //swap + p1.swap(p2); + + TEST_ASSERT_EQUAL(number1, p2->_value); + TEST_ASSERT_EQUAL(number2, p1->_value); + + p1.reset(); + p2.reset(); + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + TEST_ASSERT(!p1); + TEST_ASSERT(!p2); + } + + TEST_ASSERT_EQUAL(0, Test::_instanceCount); +} + + + +/******************* +* RAW PTR EXERCISE * +*******************/ + +/** + * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer + */ +void test_single_raw_ptr_lifetime() { + // Sanity-check value of counter + TEST_ASSERT_EQUAL(0, Test::_instanceCount); + + // Create and destroy raw pointer in given scope + { + Test t1; + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + TEST_ASSERT_EQUAL(Test::kMagicNumber, t1._value); + + Test * p1 = &t1; + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); + + const uint32_t number1 = 42; + p1->_value = number1; + TEST_ASSERT_EQUAL(number1, p1->_value); + TEST_ASSERT_EQUAL(number1, t1._value); + + p1 = nullptr; + TEST_ASSERT_EQUAL(1, Test::_instanceCount); + TEST_ASSERT(!p1); + } + + // Destroy shared pointer + TEST_ASSERT_EQUAL(0, Test::_instanceCount); +} + 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 or the // name of our Python file) @@ -103,8 +269,19 @@ static utest::v1::status_t greentea_setup(const size_t number_of_cases) { // List of test cases in this file static Case cases[] = { + // Shared test pointer Case("Test single shared pointer instance", test_single_sharedptr_lifetime), - Case("Test instance sharing across multiple shared pointers", test_instance_sharing)}; + Case("Test instance sharing across multiple shared pointers", test_instance_sharing), + + // Unique test pointer + Case("Test single unique pointer instance", test_single_unique_ptr_lifetime), + Case("Test transfer of unique pointer instance", test_unique_ptr_transfer), + Case("Test release of unique pointer instance", test_unique_ptr_release), + Case("Test swap of 2 unique ptr instance", test_unique_ptr_swap), + + // Raw test pointer + Case("Test single raw pointer instance", test_single_raw_ptr_lifetime), +}; static Specification specification(greentea_setup, cases); diff --git a/TESTS/simple-test/test-raw-ptr/main.cpp b/TESTS/simple-test/test-raw-ptr/main.cpp deleted file mode 100644 index a689d47..0000000 --- a/TESTS/simple-test/test-raw-ptr/main.cpp +++ /dev/null @@ -1,96 +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 main.cpp - * @author Sierro Yann - * - * @brief Test of raw pointer - * - * @date 2022-09-01 - * @version 0.1.0 - ***************************************************************************/ - -#include "greentea-client/test_env.h" -#include "mbed.h" -#include "unity/unity.h" -#include "utest/utest.h" - -using namespace utest::v1; -struct Test { - Test() { - _instanceCount++; - _value = kMagicNumber; - } - - ~Test() { - _instanceCount--; - _value = 0; - } - - int _value; - static constexpr uint32_t kMagicNumber = 33; - static uint32_t _instanceCount; -}; -uint32_t Test::_instanceCount = 0; - -/** - * Test that a shared pointer correctly manages the lifetime of the underlying raw pointer - */ -void test_single_raw_ptr_lifetime() { - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - - // Create and destroy raw pointer in given scope - { - Test t1; - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - TEST_ASSERT_EQUAL(Test::kMagicNumber, t1._value); - - Test * p1 = &t1; - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); - - const uint32_t number1 = 42; - p1->_value = number1; - TEST_ASSERT_EQUAL(number1, p1->_value); - TEST_ASSERT_EQUAL(number1, t1._value); - - p1 = nullptr; - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - TEST_ASSERT(!p1); - - t1.~Test(); - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - } - - // Destroy shared pointer - TEST_ASSERT_EQUAL(0, Test::_instanceCount); -} - - -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 or the - // name of our Python file) - GREENTEA_SETUP(60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -// List of test cases in this file -static Case cases[] = { - Case("Test single raw pointer instance", test_single_raw_ptr_lifetime)}; - -static Specification specification(greentea_setup, cases); - -int main() { return !Harness::run(specification); } diff --git a/TESTS/simple-test/unique-ptr/main.cpp b/TESTS/simple-test/unique-ptr/main.cpp deleted file mode 100644 index 76d5a1d..0000000 --- a/TESTS/simple-test/unique-ptr/main.cpp +++ /dev/null @@ -1,189 +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 main.cpp - * @author Sierro Yann - * - * @brief Test for std::unique_ptr template class - * - * @date 2024-10-20 - * @version 0.1.0 - ***************************************************************************/ - -#include "greentea-client/test_env.h" -#include "mbed.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include - -using namespace utest::v1; -struct Test { - Test() { - _instanceCount++; - _value = kMagicNumber; - } - - ~Test() { - _instanceCount--; - _value = 0; - } - - uint32_t _value; - static constexpr uint32_t kMagicNumber = 33; - static uint32_t _instanceCount; -}; -uint32_t Test::_instanceCount = 0; - -/* - * Check normal lifetime on a unique_ptr -*/ -void test_single_unique_ptr_lifetime() { - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - - // create and destroy a unique_ptr - { - std::unique_ptr p1 = std::make_unique(); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); - - const uint32_t number = 42; - p1->_value = number; - TEST_ASSERT_EQUAL(number, p1->_value); - - p1.reset(); - TEST_ASSERT(!p1); - } - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); -} - -/* - * Check transfer on a unique_ptr -*/ -void test_unique_ptr_transfer() { - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - - { - //create p1 - std::unique_ptr p1 = std::make_unique(); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - - //transfer p1 to p2 - std::unique_ptr p2 = std::move(p1); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - - p2.reset(); - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - TEST_ASSERT(!p1); - TEST_ASSERT(!p2); - } - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); -} - -/* - * Check the release of a unique ptr -*/ -void test_unique_ptr_release() { - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - - { - //create p1 - std::unique_ptr p1 = std::make_unique(); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - - //transfer and release p1 to p2 - Test * p2 = p1.release(); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - - delete p2; - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - TEST_ASSERT(!p1); - TEST_ASSERT(!p2); - } - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); -} - -/* - * Check the swap of 2 unique ptr -*/ -void test_unique_ptr_swap() { - // Sanity-check value of counter - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - - { - const uint32_t number1 = 65; - const uint32_t number2 = 42; - - //create p1 - std::unique_ptr p1 = std::make_unique(); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p1->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - p1->_value = number1; - TEST_ASSERT_EQUAL(number1, p1->_value); - - //create p2 - std::unique_ptr p2 = std::make_unique(); - TEST_ASSERT_EQUAL(Test::kMagicNumber, p2->_value); - TEST_ASSERT_EQUAL(1, Test::_instanceCount); - p2->_value = number2; - TEST_ASSERT_EQUAL(number2, p2->_value); - - //swap - p1.swap(p2); - - TEST_ASSERT_EQUAL(number1, p2->_value); - TEST_ASSERT_EQUAL(number2, p1->_value); - - p1.reset(); - p2.reset(); - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); - TEST_ASSERT(!p1); - TEST_ASSERT(!p2); - } - - TEST_ASSERT_EQUAL(0, Test::_instanceCount); -} - -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 or the - // name of our Python file) - GREENTEA_SETUP(60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -// List of test cases in this file -static Case cases[] = { - Case("Test single unique pointer instance", test_single_unique_ptr_lifetime), - Case("Test transfer of unique pointer instance", test_unique_ptr_transfer), - Case("Test release of unique pointer instance", test_unique_ptr_release), - Case("Test swap of 2 unique ptr instance", test_unique_ptr_swap) - - }; - -static Specification specification(greentea_setup, cases); - -int main() { return !Harness::run(specification); } \ No newline at end of file From 69047369f0bff45b6216731f8c2c38a959dbbf52 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Wed, 6 Nov 2024 14:31:04 +0100 Subject: [PATCH 14/30] FIX GitHub action --- .github/workflows/build-test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 525f524..ec09d50 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,6 +1,5 @@ name: Build test application on: - pull_request: push: jobs: @@ -13,10 +12,10 @@ jobs: strategy: matrix: target: [DISCO_H747I] - profile: [debug, release] + profile: [debug] tests: [ tests-simple-test-always-succeed, - tests-simple-test-ptr-test, + tests-simple-test-test-ptr, advdembsof_library-tests-sensors-hdc1000, tests-bike-computer-sensor-device, tests-bike-computer-speedometer From a7c28c0e525d9daf0245d524ceddbf216e7f240b Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sat, 9 Nov 2024 14:53:26 +0100 Subject: [PATCH 15/30] FIX distance calculation in speedometer. --- common/speedometer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/common/speedometer.cpp b/common/speedometer.cpp index 19ba566..c68b20a 100644 --- a/common/speedometer.cpp +++ b/common/speedometer.cpp @@ -109,7 +109,7 @@ void Speedometer::computeSpeed() { // TODO : done //Distance run with one pedal turn = tray size / rear gear size * circumference of the wheel - float ms_in_hour = static_cast(3600 * 1000); + constexpr float ms_in_hour = static_cast(3600 * 1000); float pedal_rotation_per_hour = ms_in_hour / static_cast(_pedalRotationTime.count()); float gear_ratio = static_cast(kTraySize) / static_cast(this->_gearSize); float wheel_dist_km = static_cast(this->kWheelCircumference) / 1000.0; @@ -128,11 +128,17 @@ void Speedometer::computeDistance() { // TODO : done Speedometer::computeSpeed(); // compute distance - float last_time_in_hour = static_cast(std::chrono::duration_cast(this->_lastTime).count()); - float traveled_dist = this->_currentSpeed * last_time_in_hour; + + const std::chrono::microseconds timeNow = _timer.elapsed_time(); + const std::chrono::microseconds timeDiff = timeNow - _lastTime; + constexpr float ms_in_hour = static_cast(3600 * 1000); + float traveled_dist = _currentSpeed * timeDiff.count() / (ms_in_hour*1000.0/*μs*/); + this->_totalDistanceMutex.lock(); this->_totalDistance += traveled_dist; this->_totalDistanceMutex.unlock(); + + _lastTime = _timer.elapsed_time(); } } // namespace bike_computer \ No newline at end of file From 7b62a3634ba73717253b1f7491edb7844dcdc369 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 10 Nov 2024 15:25:03 +0100 Subject: [PATCH 16/30] ADD PedalDevice --- static_scheduling/pedal_device.cpp | 72 ++++++++++++++++++++++++++++++ static_scheduling/pedal_device.hpp | 54 ++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 static_scheduling/pedal_device.cpp create mode 100644 static_scheduling/pedal_device.hpp diff --git a/static_scheduling/pedal_device.cpp b/static_scheduling/pedal_device.cpp new file mode 100644 index 0000000..9379136 --- /dev/null +++ b/static_scheduling/pedal_device.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +* @file pedal_device.cpp +* @author Rémi Heredero +* @author Yann Sierro +* +* @brief Pedal Device implementation (static scheduling) +* @date 2024-11-09 +* @version 0.1.0 +****************************************************************************/ + +#include "pedal_device.hpp" + +// from disco_h747i/wrappers +#include + +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "PedalDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling { + + static constexpr std::chrono::microseconds kTaskRunTime = 200000us; + + PedalDevice::PedalDevice(Timer& timer) : _timer(timer) {} + + + std::chrono::milliseconds PedalDevice::getCurrentRotationTime() { + // TODO + 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) { + case disco::Joystick::State::LeftPressed: + if (_pedalRotationTime < bike_computer::kMaxPedalRotationTime) { + decreaseRotationSpeed(); + hasChanged = true; + } + break; + + case disco::Joystick::State::DownPressed: + if (_pedalRotationTime > bike_computer::kMinPedalRotationTime) { + decreaseRotationSpeed(); + hasChanged = true; + } + break; + + default: + break; + } + } + elapsedTime = _timer.elapsed_time() - initialTime; + } + return _pedalRotationTime; + } + + void PedalDevice::increaseRotationSpeed() { + _pedalRotationTime -= bike_computer::kDeltaPedalRotationTime; + } + + void PedalDevice::decreaseRotationSpeed() { + _pedalRotationTime += bike_computer::kDeltaPedalRotationTime; + } + +} diff --git a/static_scheduling/pedal_device.hpp b/static_scheduling/pedal_device.hpp new file mode 100644 index 0000000..3f5c489 --- /dev/null +++ b/static_scheduling/pedal_device.hpp @@ -0,0 +1,54 @@ +// 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 + * + * @brief Pedal System header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace static_scheduling { + +class PedalDevice { + public: + explicit PedalDevice(Timer& timer); // NOLINT(runtime/references) + + // make the class non copyable + PedalDevice(PedalDevice&) = delete; + PedalDevice& operator=(PedalDevice&) = delete; + + // method called for updating the bike system + std::chrono::milliseconds getCurrentRotationTime(); + + private: + // private methods + void increaseRotationSpeed(); + void decreaseRotationSpeed(); + + // data members + std::chrono::milliseconds _pedalRotationTime = + bike_computer::kInitialPedalRotationTime; + Timer& _timer; +}; + +} // namespace static_scheduling \ No newline at end of file From 874a968f5cba6ef8c29c5b675c03aa8c78e7d34c Mon Sep 17 00:00:00 2001 From: Klagarge Date: Tue, 12 Nov 2024 15:17:17 +0100 Subject: [PATCH 17/30] ADD ResetDevice --- static_scheduling/reset_device.cpp | 59 ++++++++++++++++++++++++++++++ static_scheduling/reset_device.hpp | 56 ++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 static_scheduling/reset_device.cpp create mode 100644 static_scheduling/reset_device.hpp diff --git a/static_scheduling/reset_device.cpp b/static_scheduling/reset_device.cpp new file mode 100644 index 0000000..6447f59 --- /dev/null +++ b/static_scheduling/reset_device.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +* @file pedal_device.cpp +* @author Rémi Heredero +* @author Yann Sierro +* +* @brief Pedal Device implementation (static scheduling) +* @date 2024-11-12 +* @version 0.1.0 +****************************************************************************/ + +#include "reset_device.h" + +// from disco_h747i/wrappers +#include + +#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 "PedalDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling { + + static constexpr std::chrono::microseconds kTaskRunTime = 1000000us; + + ResetDevice::ResetDevice(Timer& timer) : timer_(timer) {} + + std::chrono::milliseconds ResetDevice::checkReset() { + 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 isPressed = false; + while (elapsedTime < kTaskRunTime) { + if(!hasChanged) { + isPressed = _resetButton.read() == kPolarityPressed; + } + elapsedTime = _timer.elapsed_time() - initialTime; + } + + } + + std::chrono::microseconds ResetDevice::getPressTime() { + return _pressTime; + } + + void ResetDevice::onRise() { + _pressTime = _timer.elapsed_time(); + } + + + +} \ No newline at end of file diff --git a/static_scheduling/reset_device.hpp b/static_scheduling/reset_device.hpp new file mode 100644 index 0000000..e5d1b2f --- /dev/null +++ b/static_scheduling/reset_device.hpp @@ -0,0 +1,56 @@ +// 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 + * + * @brief ResetDevice header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "mbed.h" + +namespace static_scheduling { + +class ResetDevice { + public: + explicit ResetDevice(Timer& timer); // NOLINT(runtime/references) + + // make the class non copyable + ResetDevice(ResetDevice&) = delete; + ResetDevice& operator=(ResetDevice&) = delete; + + // method called for checking the reset status + bool checkReset(); + + // for computing the response time + std::chrono::microseconds getPressTime(); + + private: + // called when the button is pressed + void onRise(); + + // data members + // instance representing the reset button + InterruptIn _resetButton; + Timer& _timer; + std::chrono::microseconds _pressTime; +}; + +} // namespace static_scheduling \ No newline at end of file From 6d0452d9ca2dce52d5d2163a68fe01668272b075 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Tue, 12 Nov 2024 15:52:39 +0100 Subject: [PATCH 18/30] FIX ResetDevice - Initialisation - Callback - return of checkReset --- static_scheduling/reset_device.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/static_scheduling/reset_device.cpp b/static_scheduling/reset_device.cpp index 6447f59..bda773c 100644 --- a/static_scheduling/reset_device.cpp +++ b/static_scheduling/reset_device.cpp @@ -1,14 +1,14 @@ /**************************************************************************** -* @file pedal_device.cpp +* @file reset_device.cpp * @author Rémi Heredero * @author Yann Sierro * -* @brief Pedal Device implementation (static scheduling) +* @brief Reset Device implementation (static scheduling) * @date 2024-11-12 * @version 0.1.0 ****************************************************************************/ -#include "reset_device.h" +#include "reset_device.hpp" // from disco_h747i/wrappers #include @@ -30,20 +30,24 @@ namespace static_scheduling { static constexpr std::chrono::microseconds kTaskRunTime = 1000000us; - ResetDevice::ResetDevice(Timer& timer) : timer_(timer) {} + ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) { + _resetButton.rise(callback(this, &ResetDevice::onRise)); + } - std::chrono::milliseconds ResetDevice::checkReset() { + bool ResetDevice::checkReset() { 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 isPressed = false; while (elapsedTime < kTaskRunTime) { - if(!hasChanged) { + if(!isPressed) { isPressed = _resetButton.read() == kPolarityPressed; } elapsedTime = _timer.elapsed_time() - initialTime; } + return isPressed; + } std::chrono::microseconds ResetDevice::getPressTime() { From ed9ab169bb5a33e6444106aa52bc7941fc168c7c Mon Sep 17 00:00:00 2001 From: Klagarge Date: Tue, 12 Nov 2024 15:54:07 +0100 Subject: [PATCH 19/30] CHG switch CI trigger from push to pull_request --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ec09d50..00d3f8b 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,6 +1,6 @@ name: Build test application on: - push: + pull_request: jobs: build-cli-v1: From 4c174ce444e0fd839d1e73866817eaba88c397e7 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 17 Nov 2024 14:20:38 +0100 Subject: [PATCH 20/30] ADD bike-system super-loop with while --- TESTS/bike-computer/bike-system/main.cpp | 88 +++++++++ main.cpp | 19 +- static_scheduling/bike_system.cpp | 233 +++++++++++++++++++++++ static_scheduling/bike_system.hpp | 98 ++++++++++ static_scheduling/reset_device.cpp | 2 +- 5 files changed, 434 insertions(+), 6 deletions(-) create mode 100644 TESTS/bike-computer/bike-system/main.cpp create mode 100644 static_scheduling/bike_system.cpp create mode 100644 static_scheduling/bike_system.hpp diff --git a/TESTS/bike-computer/bike-system/main.cpp b/TESTS/bike-computer/bike-system/main.cpp new file mode 100644 index 0000000..f3a57cd --- /dev/null +++ b/TESTS/bike-computer/bike-system/main.cpp @@ -0,0 +1,88 @@ +// 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 main.cpp + * @author Serge Ayer + * + * @brief Bike computer test suite: scheduling + * + * @date 2023-08-26 + * @version 0.1.0 + ***************************************************************************/ + +#include + +#include "static_scheduling/bike_system.hpp" + +#include "greentea-client/test_env.h" +#include "mbed.h" +#include "task_logger.hpp" +#include "unity/unity.h" +#include "utest/utest.h" + +using namespace utest::v1; + +// test_bike_system handler function +static void test_bike_system() { + // create the BikeSystem instance + static_scheduling::BikeSystem bikeSystem; + + // run the bike system in a separate thread + Thread thread; + thread.start(callback(&bikeSystem, &static_scheduling::BikeSystem::start)); + + // let the bike system run for 20 secs + ThisThread::sleep_for(20s); + + // stop the bike system + bikeSystem.stop(); + + // check whether scheduling was correct + // Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex, + // kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index + constexpr std::chrono::microseconds taskComputationTimes[] = { + 100000us, 200000us, 100000us, 100000us, 200000us, 100000us}; + constexpr std::chrono::microseconds taskPeriods[] = { + 800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; + + // allow for 2 msecs offset + uint64_t deltaUs = 2000; + for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; + taskIndex++) { + TEST_ASSERT_UINT64_WITHIN( + deltaUs, + taskPeriods[taskIndex].count(), + bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); + TEST_ASSERT_UINT64_WITHIN( + deltaUs, + taskComputationTimes[taskIndex].count(), + bikeSystem.getTaskLogger().getComputationTime(taskIndex).count()); + } +} + +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 or the + // name of our Python file) + GREENTEA_SETUP(180, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +// List of test cases in this file +static Case cases[] = {Case("test bike system", test_bike_system)}; + +static Specification specification(greentea_setup, cases); + +int main() { return !Harness::run(specification); } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 9bb6191..c777a16 100644 --- a/main.cpp +++ b/main.cpp @@ -6,19 +6,28 @@ #if !MBED_TEST_MODE #include "mbed.h" // NOLINT +#include "mbed_trace.h" +#include "static_scheduling/bike_system.hpp" // Blinking rate in milliseconds #define BLINKING_RATE 500ms +#define TRACE_GROUP "MAIN" + int main() { // Initialise the digital pin LED1 as an output - DigitalOut led(LED1); + mbed_trace_init(); + // DigitalOut led(LED1); + // tr_debug("Hello world"); - while (true) { - led = !led; - ThisThread::sleep_for(BLINKING_RATE); - } + // while (true) { + // led = !led; + // ThisThread::sleep_for(BLINKING_RATE); + // tr_debug("blink"); + // } + static_scheduling::BikeSystem bikeSystem; + bikeSystem.start(); } #endif // MBED_TEST_MODE diff --git a/static_scheduling/bike_system.cpp b/static_scheduling/bike_system.cpp new file mode 100644 index 0000000..b62ec22 --- /dev/null +++ b/static_scheduling/bike_system.cpp @@ -0,0 +1,233 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief Bike System implementation (static scheduling) + * + * @date 2023-11-15 + * @version 1.1.0 + ***************************************************************************/ + +#include "bike_system.hpp" + +#include + +#include "mbed_trace.h" +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "BikeSystem" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling { + +static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms; +static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms; +static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms; +static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms; +static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 0ms; // 0 or 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 kResetTaskPeriod = 800ms; +static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms; +static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms; +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 kDisplayTask2Period = 1600ms; +static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; +static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; + +// TODO: implement the constructor + +BikeSystem::BikeSystem() : + _gearDevice(_timer), + _pedalDevice(_timer), + _resetDevice(_timer), + _speedometer(_timer) +{ + +} + +void BikeSystem::start() { + tr_info("Starting Super-Loop without event handling"); + + init(); + + // TODO: implement the super-loop based for implementing the appropriate schedule + // Done + while (true) { + auto startTime = _timer.elapsed_time(); + + // TODO: implement calls to different tasks based on computed schedule + // Done + gearTask(); // 100ms : 0ms -> 100ms + speedDistanceTask(); // 200ms : 100ms -> 300ms + displayTask1(); // 200ms : 300ms -> 500ms + speedDistanceTask(); // 200ms : 500ms -> 700ms + resetTask(); // 100ms : 700ms -> 800ms + gearTask(); // 100ms : 800ms -> 900ms + speedDistanceTask(); // 200ms : 900ms -> 1100ms + temperatureTask(); // 100ms : 1100ms -> 1200ms + displayTask2(); // 100ms : 1200ms -> 1300ms + speedDistanceTask(); // 200ms : 1300ms -> 1500ms + resetTask(); // 100ms : 1500ms -> 1600ms + + + + // register the time at the end of the cyclic schedule period and print the + // elapsed time for the period + std::chrono::microseconds endTime = _timer.elapsed_time(); + const auto cycle = + std::chrono::duration_cast(endTime - startTime); + tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count()); + + // TODO: implement loop exit when applicable + // Done + bool fStop = false; + core_util_atomic_load(&fStop); + if (fStop) { + break; + } + + } +} + +void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } + +#if defined(MBED_TEST_MODE) +const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; } +#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("Failed to initialized the lcd display: %d", static_cast(rc)); + } + + // initialize the sensor device + bool present = _sensorDevice.init(); + if (!present) { + tr_error("Sensor not present or initialization failed"); + } + + // enable/disable task logging + _taskLogger.enable(true); +} + +void BikeSystem::gearTask() { + // gear task + auto taskStartTime = _timer.elapsed_time(); + + // no need to protect access to data members (single threaded) + _currentGear = _gearDevice.getCurrentGear(); + _currentGearSize = _gearDevice.getCurrentGearSize(); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); +} + +void BikeSystem::speedDistanceTask() { + // speed and distance task + auto taskStartTime = _timer.elapsed_time(); + + const auto pedalRotationTime = _pedalDevice.getCurrentRotationTime(); + _speedometer.setCurrentRotationTime(pedalRotationTime); + _speedometer.setGearSize(_currentGearSize); + // no need to protect access to data members (single threaded) + _currentSpeed = _speedometer.getCurrentSpeed(); + _traveledDistance = _speedometer.getDistance(); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); +} + +void BikeSystem::temperatureTask() { + auto taskStartTime = _timer.elapsed_time(); + + 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()); + + // 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::kTemperatureTaskIndex, taskStartTime); +} + +void BikeSystem::resetTask() { + auto taskStartTime = _timer.elapsed_time(); + + if (_resetDevice.checkReset()) { + std::chrono::microseconds responseTime = + _timer.elapsed_time() - _resetDevice.getPressTime(); + tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); + _speedometer.reset(); + } + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); +} + +void BikeSystem::displayTask1() { + auto taskStartTime = _timer.elapsed_time(); + + _displayDevice.displayGear(_currentGear); + _displayDevice.displaySpeed(_currentSpeed); + _displayDevice.displayDistance(_traveledDistance); + + // 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::kDisplayTask1Index, taskStartTime); +} + +void BikeSystem::displayTask2() { + auto taskStartTime = _timer.elapsed_time(); + + _displayDevice.displayTemperature(_currentTemperature); + + // 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); +} + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling/bike_system.hpp b/static_scheduling/bike_system.hpp new file mode 100644 index 0000000..445ccad --- /dev/null +++ b/static_scheduling/bike_system.hpp @@ -0,0 +1,98 @@ +// 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 + * + * @brief Bike System header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +// from advembsof +#include "display_device.hpp" +#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 static_scheduling { + +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(); +#endif // defined(MBED_TEST_MODE) + + private: + // private methods + void init(); + void gearTask(); + void speedDistanceTask(); + void temperatureTask(); + void resetTask(); + void displayTask1(); + void displayTask2(); + + // stop flag, used for stopping the super-loop (set in stop()) + bool _stopFlag = false; + // timer instance used for loggint task time and used by ResetDevice + Timer _timer; + // data member that represents the device for manipulating the gear + GearDevice _gearDevice; + uint8_t _currentGear = bike_computer::kMinGear; + uint8_t _currentGearSize = bike_computer::kMinGearSize; + // data member that represents the device for manipulating the pedal rotation + // speed/time + PedalDevice _pedalDevice; + 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; +}; + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling/reset_device.cpp b/static_scheduling/reset_device.cpp index bda773c..9b35df4 100644 --- a/static_scheduling/reset_device.cpp +++ b/static_scheduling/reset_device.cpp @@ -28,7 +28,7 @@ static constexpr uint8_t kPolarityPressed = 1; namespace static_scheduling { - static constexpr std::chrono::microseconds kTaskRunTime = 1000000us; + static constexpr std::chrono::microseconds kTaskRunTime = 100000us; ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) { _resetButton.rise(callback(this, &ResetDevice::onRise)); From c66c8a0963296eff44453de7983885fbf7ad19f5 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 17 Nov 2024 18:25:48 +0100 Subject: [PATCH 21/30] ADD cpu logger --- README.md | 4 ++++ mbed_app.json | 1 + static_scheduling/bike_system.cpp | 20 +++++++++++--------- static_scheduling/bike_system.hpp | 4 ++++ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 73349c5..938c038 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,7 @@ Test sensor libraries : ```terminal mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run ``` + +# Some questions +## 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. \ No newline at end of file diff --git a/mbed_app.json b/mbed_app.json index 2f706a5..c42f542 100644 --- a/mbed_app.json +++ b/mbed_app.json @@ -14,6 +14,7 @@ "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 diff --git a/static_scheduling/bike_system.cpp b/static_scheduling/bike_system.cpp index b62ec22..8bdb6ea 100644 --- a/static_scheduling/bike_system.cpp +++ b/static_scheduling/bike_system.cpp @@ -54,13 +54,13 @@ static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; -// TODO: implement the constructor BikeSystem::BikeSystem() : _gearDevice(_timer), _pedalDevice(_timer), _resetDevice(_timer), - _speedometer(_timer) + _speedometer(_timer), + _cpuLogger(_timer) { } @@ -70,14 +70,10 @@ void BikeSystem::start() { init(); - // TODO: implement the super-loop based for implementing the appropriate schedule - // Done while (true) { auto startTime = _timer.elapsed_time(); - // TODO: implement calls to different tasks based on computed schedule - // Done - gearTask(); // 100ms : 0ms -> 100ms + gearTask(); // 100ms : 0ms -> 100ms speedDistanceTask(); // 200ms : 100ms -> 300ms displayTask1(); // 200ms : 300ms -> 500ms speedDistanceTask(); // 200ms : 500ms -> 700ms @@ -106,6 +102,10 @@ void BikeSystem::start() { break; } + #if !defined(MBED_TEST_MODE) + _cpuLogger.printStats(); + #endif + } } @@ -144,7 +144,8 @@ void BikeSystem::gearTask() { _currentGearSize = _gearDevice.getCurrentGearSize(); _taskLogger.logPeriodAndExecutionTime( - _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); + _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime + ); } void BikeSystem::speedDistanceTask() { @@ -159,7 +160,8 @@ void BikeSystem::speedDistanceTask() { _traveledDistance = _speedometer.getDistance(); _taskLogger.logPeriodAndExecutionTime( - _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); + _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime + ); } void BikeSystem::temperatureTask() { diff --git a/static_scheduling/bike_system.hpp b/static_scheduling/bike_system.hpp index 445ccad..8a1ccc6 100644 --- a/static_scheduling/bike_system.hpp +++ b/static_scheduling/bike_system.hpp @@ -27,6 +27,7 @@ // from advembsof #include "display_device.hpp" #include "task_logger.hpp" +#include "cpu_logger.hpp" // from common #include "sensor_device.hpp" @@ -93,6 +94,9 @@ class BikeSystem { // used for logging task info advembsof::TaskLogger _taskLogger; + + // cpu logger to measure cpu usage + advembsof::CPULogger _cpuLogger; }; } // namespace static_scheduling \ No newline at end of file From b52f4761242c29bbe5a45545f56ea6683defba46 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 17 Nov 2024 18:26:18 +0100 Subject: [PATCH 22/30] ADD Thread sleep --- README.md | 5 +++- static_scheduling/bike_system.cpp | 42 ++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 938c038..fbe9625 100644 --- a/README.md +++ b/README.md @@ -25,4 +25,7 @@ mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 # Some questions ## 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. \ No newline at end of file +We observe a 100% usage because on each CPU cycle it compare if time is done. + +## 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? +We can observe only a usage of 75% because the CPU is more on Idle with Thread sleep. \ No newline at end of file diff --git a/static_scheduling/bike_system.cpp b/static_scheduling/bike_system.cpp index 8bdb6ea..02b31ad 100644 --- a/static_scheduling/bike_system.cpp +++ b/static_scheduling/bike_system.cpp @@ -174,12 +174,18 @@ void BikeSystem::temperatureTask() { tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count()); + ThisThread::sleep_for( + std::chrono::duration_cast( + 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; - } +// std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); +// while (elapsedTime < kTemperatureTaskComputationTime) { +// elapsedTime = _timer.elapsed_time() - taskStartTime; +// } _taskLogger.logPeriodAndExecutionTime( _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); @@ -206,12 +212,18 @@ void BikeSystem::displayTask1() { _displayDevice.displaySpeed(_currentSpeed); _displayDevice.displayDistance(_traveledDistance); + ThisThread::sleep_for( + std::chrono::duration_cast( + 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; - } +// std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); +// while (elapsedTime < kDisplayTask1ComputationTime) { +// elapsedTime = _timer.elapsed_time() - taskStartTime; +// } _taskLogger.logPeriodAndExecutionTime( _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); @@ -222,12 +234,18 @@ void BikeSystem::displayTask2() { _displayDevice.displayTemperature(_currentTemperature); + ThisThread::sleep_for( + std::chrono::duration_cast( + 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; - } +// std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); +// while (elapsedTime < kDisplayTask2ComputationTime) { +// elapsedTime = _timer.elapsed_time() - taskStartTime; +// } _taskLogger.logPeriodAndExecutionTime( _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); } From 0bd561b9478ef7f1a3a8612c5ce33ee8e26cbfe9 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 17 Nov 2024 19:13:06 +0100 Subject: [PATCH 23/30] ADD EventQueue for static_scheduling --- TESTS/bike-computer/bike-system/main.cpp | 38 +++++++++++++++- main.cpp | 3 +- static_scheduling/bike_system.cpp | 55 ++++++++++++++++++++++++ static_scheduling/bike_system.hpp | 4 ++ 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/TESTS/bike-computer/bike-system/main.cpp b/TESTS/bike-computer/bike-system/main.cpp index f3a57cd..c1c4091 100644 --- a/TESTS/bike-computer/bike-system/main.cpp +++ b/TESTS/bike-computer/bike-system/main.cpp @@ -72,6 +72,39 @@ static void test_bike_system() { } } +// test_bike_system_event_queue handler function +static void test_bike_system_event_queue() { + // create the BikeSystem instance + static_scheduling::BikeSystem bikeSystem; + + // run the bike system in a separate thread + Thread thread; + thread.start(callback(&bikeSystem, &static_scheduling::BikeSystem::startWithEventQueue)); + + // let the bike system run for 20 secs + ThisThread::sleep_for(20s); + + // stop the bike system + bikeSystem.stop(); + + // check whether scheduling was correct + // Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex, + // kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index + // When we use the event queue, 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) + uint64_t deltaUs = 2000; + for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; + taskIndex++) { + TEST_ASSERT_UINT64_WITHIN( + deltaUs, + taskPeriods[taskIndex].count(), + bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); + } +} + 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 or the // name of our Python file) @@ -81,7 +114,10 @@ static utest::v1::status_t greentea_setup(const size_t number_of_cases) { } // List of test cases in this file -static Case cases[] = {Case("test bike system", test_bike_system)}; +static Case cases[] = { + Case("test bike system", test_bike_system), + Case("test bike system with event queue", test_bike_system_event_queue) +}; static Specification specification(greentea_setup, cases); diff --git a/main.cpp b/main.cpp index c777a16..1c7fa3d 100644 --- a/main.cpp +++ b/main.cpp @@ -27,7 +27,8 @@ int main() { // tr_debug("blink"); // } static_scheduling::BikeSystem bikeSystem; - bikeSystem.start(); + // bikeSystem.start(); + bikeSystem.startWithEventQueue(); } #endif // MBED_TEST_MODE diff --git a/static_scheduling/bike_system.cpp b/static_scheduling/bike_system.cpp index 02b31ad..74a4040 100644 --- a/static_scheduling/bike_system.cpp +++ b/static_scheduling/bike_system.cpp @@ -53,6 +53,9 @@ static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime = 10 static constexpr std::chrono::milliseconds kDisplayTask2Period = 1600ms; static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; +static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms; +static constexpr std::chrono::milliseconds kCPUTaskDelay = 0ms; +static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 0ms; BikeSystem::BikeSystem() : @@ -109,6 +112,54 @@ void BikeSystem::start() { } } +void BikeSystem::startWithEventQueue() { + + tr_info("Starting Super-Loop with event handling"); + + init(); + + EventQueue eventQueue; + + Event gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); + gearEvent.delay(kGearTaskDelay); + gearEvent.period(kGearTaskPeriod); + gearEvent.post(); + + Event speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask)); + speedDistanceEvent.delay(kSpeedDistanceTaskDelay); + speedDistanceEvent.period(kSpeedDistanceTaskPeriod); + speedDistanceEvent.post(); + + Event display1Event(&eventQueue, callback(this, &BikeSystem::displayTask1)); + display1Event.delay(kDisplayTask1Delay); + display1Event.period(kDisplayTask1Period); + display1Event.post(); + + Event resetEvent(&eventQueue, callback(this, &BikeSystem::resetTask)); + resetEvent.delay(kResetTaskDelay); + resetEvent.period(kResetTaskPeriod); + resetEvent.post(); + + Event temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask)); + temperatureEvent.delay(kTemperatureTaskDelay); + temperatureEvent.period(kTemperatureTaskPeriod); + temperatureEvent.post(); + + Event display2Event(&eventQueue, callback(this, &BikeSystem::displayTask2)); + display2Event.delay(kDisplayTask2Delay); + display2Event.period(kDisplayTask2Period); + display2Event.post(); + + #if !defined(MBED_TEST_MODE) + Event cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); + cpuEvent.delay(kCPUTaskDelay); + cpuEvent.period(kCPUTaskPeriod); + cpuEvent.post(); + #endif + + eventQueue.dispatch_forever(); +} + void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } #if defined(MBED_TEST_MODE) @@ -250,4 +301,8 @@ void BikeSystem::displayTask2() { _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); } +void BikeSystem::cpuTask() { + _cpuLogger.printStats(); +} + } // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling/bike_system.hpp b/static_scheduling/bike_system.hpp index 8a1ccc6..ccd3409 100644 --- a/static_scheduling/bike_system.hpp +++ b/static_scheduling/bike_system.hpp @@ -52,6 +52,9 @@ class BikeSystem { // method called in main() for starting the system void start(); + // method called in main() for starting the sysytem with the event queue + void startWithEventQueue(); + // method called for stopping the system void stop(); @@ -68,6 +71,7 @@ class BikeSystem { void resetTask(); void displayTask1(); void displayTask2(); + void cpuTask(); // stop flag, used for stopping the super-loop (set in stop()) bool _stopFlag = false; From 35d2d76bca6cf5a9d6331a7b0268225cfc05a728 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Sun, 17 Nov 2024 23:09:00 +0100 Subject: [PATCH 24/30] ADD [WIP] Static scheduling with event --- TESTS/bike-computer/bike-system/main.cpp | 35 +++ common/constants.hpp | 6 + main.cpp | 22 +- static_scheduling/reset_device.cpp | 2 +- static_scheduling_with_event/bike_system.cpp | 295 ++++++++++++++++++ static_scheduling_with_event/bike_system.hpp | 111 +++++++ static_scheduling_with_event/gear_device.cpp | 69 ++++ static_scheduling_with_event/gear_device.hpp | 54 ++++ static_scheduling_with_event/pedal_device.cpp | 62 ++++ static_scheduling_with_event/pedal_device.hpp | 60 ++++ static_scheduling_with_event/reset_device.cpp | 36 +++ static_scheduling_with_event/reset_device.hpp | 48 +++ 12 files changed, 783 insertions(+), 17 deletions(-) create mode 100644 static_scheduling_with_event/bike_system.cpp create mode 100644 static_scheduling_with_event/bike_system.hpp create mode 100644 static_scheduling_with_event/gear_device.cpp create mode 100644 static_scheduling_with_event/gear_device.hpp create mode 100644 static_scheduling_with_event/pedal_device.cpp create mode 100644 static_scheduling_with_event/pedal_device.hpp create mode 100644 static_scheduling_with_event/reset_device.cpp create mode 100644 static_scheduling_with_event/reset_device.hpp diff --git a/TESTS/bike-computer/bike-system/main.cpp b/TESTS/bike-computer/bike-system/main.cpp index c1c4091..e173b9a 100644 --- a/TESTS/bike-computer/bike-system/main.cpp +++ b/TESTS/bike-computer/bike-system/main.cpp @@ -25,6 +25,7 @@ #include #include "static_scheduling/bike_system.hpp" +#include "static_scheduling_with_event/bike_system.hpp" #include "greentea-client/test_env.h" #include "mbed.h" @@ -105,6 +106,39 @@ static void test_bike_system_event_queue() { } } +// test_bike_system_with_event handler function +static void test_bike_system_with_event() { + // create the BikeSystem instance + static_scheduling_with_event::BikeSystem bikeSystem; + + // run the bike system in a separate thread + Thread thread; + thread.start(callback(&bikeSystem, &static_scheduling_with_event::BikeSystem::start)); + + // let the bike system run for 20 secs + ThisThread::sleep_for(20s); + + // stop the bike system + bikeSystem.stop(); + + // 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) + uint64_t deltaUs = 2000; + for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; + taskIndex++) { + TEST_ASSERT_UINT64_WITHIN( + deltaUs, + taskPeriods[taskIndex].count(), + bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); + } +} + 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 or the // name of our Python file) @@ -117,6 +151,7 @@ static utest::v1::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 handling", test_bike_system_with_event), }; static Specification specification(greentea_setup, cases); diff --git a/common/constants.hpp b/common/constants.hpp index 8774f8f..859a210 100644 --- a/common/constants.hpp +++ b/common/constants.hpp @@ -51,4 +51,10 @@ static constexpr std::chrono::milliseconds kMaxPedalRotationTime = 1500ms; // definition of pedal rotation time change upon acceleration/deceleration static constexpr std::chrono::milliseconds kDeltaPedalRotationTime = 25ms; +static constexpr uint32_t kNbrOfSteps = static_cast( + ( + bike_computer::kMaxPedalRotationTime - bike_computer::kMinPedalRotationTime + ).count() / bike_computer::kDeltaPedalRotationTime.count() +); + } // namespace bike_computer \ No newline at end of file diff --git a/main.cpp b/main.cpp index 1c7fa3d..b9e8ed2 100644 --- a/main.cpp +++ b/main.cpp @@ -7,27 +7,17 @@ #include "mbed.h" // NOLINT #include "mbed_trace.h" -#include "static_scheduling/bike_system.hpp" - -// Blinking rate in milliseconds -#define BLINKING_RATE 500ms +#include "static_scheduling_with_event/bike_system.hpp" +#if defined(MBED_CONF_MBED_TRACE_ENABLE) #define TRACE_GROUP "MAIN" +#endif // MBED_CONF_MBED_TRACE_ENAB int main() { - // Initialise the digital pin LED1 as an output - +#if defined(MBED_CONF_MBED_TRACE_ENABLE) mbed_trace_init(); - // DigitalOut led(LED1); - // tr_debug("Hello world"); - - // while (true) { - // led = !led; - // ThisThread::sleep_for(BLINKING_RATE); - // tr_debug("blink"); - // } - static_scheduling::BikeSystem bikeSystem; - // bikeSystem.start(); +#endif + static_scheduling_with_event::BikeSystem bikeSystem; bikeSystem.startWithEventQueue(); } diff --git a/static_scheduling/reset_device.cpp b/static_scheduling/reset_device.cpp index 9b35df4..e7ebcc0 100644 --- a/static_scheduling/reset_device.cpp +++ b/static_scheduling/reset_device.cpp @@ -23,7 +23,7 @@ static constexpr uint8_t kPolarityPressed = 1; #if MBED_CONF_MBED_TRACE_ENABLE -#define TRACE_GROUP "PedalDevice" +#define TRACE_GROUP "ResetDevice" #endif // MBED_CONF_MBED_TRACE_ENABLE namespace static_scheduling { diff --git a/static_scheduling_with_event/bike_system.cpp b/static_scheduling_with_event/bike_system.cpp new file mode 100644 index 0000000..b97a0b3 --- /dev/null +++ b/static_scheduling_with_event/bike_system.cpp @@ -0,0 +1,295 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief Bike System implementation (static scheduling) + * + * @date 2023-11-15 + * @version 1.1.0 + ***************************************************************************/ + +#include "bike_system.hpp" + +#include + +#include "mbed_trace.h" +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "BikeSystem" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling_with_event { + +static constexpr std::chrono::milliseconds kGearTaskPeriod = 800ms; +static constexpr std::chrono::milliseconds kGearTaskDelay = 0ms; +static constexpr std::chrono::milliseconds kGearTaskComputationTime = 100ms; + +static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod = 400ms; +static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay = 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 kResetTaskPeriod = 800ms; +static constexpr std::chrono::milliseconds kResetTaskDelay = 700ms; +static constexpr std::chrono::milliseconds kResetTaskComputationTime = 100ms; + +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 kDisplayTask2Period = 1600ms; +static constexpr std::chrono::milliseconds kDisplayTask2Delay = 1200ms; +static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime = 100ms; + +static constexpr std::chrono::milliseconds kCPUTaskPeriod = 1600ms; +static constexpr std::chrono::milliseconds kCPUTaskDelay = 1200ms; +static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 100ms; + + +BikeSystem::BikeSystem() : + _gearDevice(), + _pedalDevice(), + _resetDevice(callback(this, &BikeSystem::onReset)), + _speedometer(_timer), + _cpuLogger(_timer) +{ + +} + +void BikeSystem::start() { + tr_info("Starting Super-Loop without event handling"); + + init(); + + while (true) { + auto startTime = _timer.elapsed_time(); + + gearTask(); // 100ms : 0ms -> 100ms + speedDistanceTask(); // 200ms : 100ms -> 300ms + displayTask1(); // 200ms : 300ms -> 500ms + speedDistanceTask(); // 200ms : 500ms -> 700ms + resetTask(); // 100ms : 700ms -> 800ms + gearTask(); // 100ms : 800ms -> 900ms + speedDistanceTask(); // 200ms : 900ms -> 1100ms + temperatureTask(); // 100ms : 1100ms -> 1200ms + displayTask2(); // 100ms : 1200ms -> 1300ms + speedDistanceTask(); // 200ms : 1300ms -> 1500ms + resetTask(); // 100ms : 1500ms -> 1600ms + + + + // register the time at the end of the cyclic schedule period and print the + // elapsed time for the period + std::chrono::microseconds endTime = _timer.elapsed_time(); + const auto cycle = + std::chrono::duration_cast(endTime - startTime); + tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count()); + + bool stopFlag = false; + core_util_atomic_load(&stopFlag); + if (stopFlag) { + break; + } + + #if !defined(MBED_TEST_MODE) + _cpuLogger.printStats(); + #endif + + } +} + +void BikeSystem::startWithEventQueue() { + + tr_info("Starting Super-Loop with event handling"); + + init(); + + EventQueue eventQueue; + + Event gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); + gearEvent.delay(kGearTaskDelay); + gearEvent.period(kGearTaskPeriod); + gearEvent.post(); + + Event speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask)); + speedDistanceEvent.delay(kSpeedDistanceTaskDelay); + speedDistanceEvent.period(kSpeedDistanceTaskPeriod); + speedDistanceEvent.post(); + + Event display1Event(&eventQueue, callback(this, &BikeSystem::displayTask1)); + display1Event.delay(kDisplayTask1Delay); + display1Event.period(kDisplayTask1Period); + display1Event.post(); + + Event resetEvent(&eventQueue, callback(this, &BikeSystem::resetTask)); + resetEvent.delay(kResetTaskDelay); + resetEvent.period(kResetTaskPeriod); + resetEvent.post(); + + Event temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask)); + temperatureEvent.delay(kTemperatureTaskDelay); + temperatureEvent.period(kTemperatureTaskPeriod); + temperatureEvent.post(); + + Event display2Event(&eventQueue, callback(this, &BikeSystem::displayTask2)); + display2Event.delay(kDisplayTask2Delay); + display2Event.period(kDisplayTask2Period); + display2Event.post(); + + #if !defined(MBED_TEST_MODE) + Event cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); + cpuEvent.delay(kCPUTaskDelay); + cpuEvent.period(kCPUTaskPeriod); + cpuEvent.post(); + #endif + + eventQueue.dispatch_forever(); +} + +void BikeSystem::onReset() { + _resetTime = _timer.elapsed_time(); + core_util_atomic_store_bool(&_resetFlag, true); +} + +void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } + +#if defined(MBED_TEST_MODE) +const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; } +#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("Failed to initialized the lcd display: %d", static_cast(rc)); + } + + // initialize the sensor device + bool present = _sensorDevice.init(); + if (!present) { + tr_error("Sensor not present or initialization failed"); + } + + // enable/disable task logging + _taskLogger.enable(true); +} + +void BikeSystem::gearTask() { + // gear task + auto taskStartTime = _timer.elapsed_time(); + + // no need to protect access to data members (single threaded) + _currentGear = _gearDevice.getCurrentGear(); + _currentGearSize = _gearDevice.getCurrentGearSize(); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime + ); +} + +void BikeSystem::speedDistanceTask() { + auto taskStartTime = _timer.elapsed_time(); + + const auto pedalRotationTime = _pedalDevice.getCurrentRotationTime(); + _speedometer.setCurrentRotationTime(pedalRotationTime); + _speedometer.setGearSize(_currentGearSize); + + _currentSpeed = _speedometer.getCurrentSpeed(); + _traveledDistance = _speedometer.getDistance(); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime + ); +} + +void BikeSystem::temperatureTask() { + auto taskStartTime = _timer.elapsed_time(); + + //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( + kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime) + ) + ); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); +} + +void BikeSystem::resetTask() { + auto taskStartTime = _timer.elapsed_time(); + + if (core_util_atomic_load_bool(&_resetFlag)) { + std::chrono::microseconds responseTime = _timer.elapsed_time() - _resetTime; + tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); + _speedometer.reset(); + } + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); +} + +void BikeSystem::displayTask1() { + auto taskStartTime = _timer.elapsed_time(); + + _displayDevice.displayGear(_currentGear); + _displayDevice.displaySpeed(_currentSpeed); + _displayDevice.displayDistance(_traveledDistance); + + ThisThread::sleep_for( + std::chrono::duration_cast( + kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime) + ) + ); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); +} + +void BikeSystem::displayTask2() { + auto taskStartTime = _timer.elapsed_time(); + + _displayDevice.displayTemperature(_currentTemperature); + + ThisThread::sleep_for( + std::chrono::duration_cast( + kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime) + ) + ); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); +} + +void BikeSystem::cpuTask() { + _cpuLogger.printStats(); +} + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling_with_event/bike_system.hpp b/static_scheduling_with_event/bike_system.hpp new file mode 100644 index 0000000..3bf3f97 --- /dev/null +++ b/static_scheduling_with_event/bike_system.hpp @@ -0,0 +1,111 @@ +// 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 + * + * @brief Bike System header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +// from advembsof +#include "display_device.hpp" +#include "task_logger.hpp" +#include "cpu_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 static_scheduling_with_event { + +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 in main() for starting the sysytem with the event queue + void startWithEventQueue(); + + // method called for stopping the system + void stop(); + +#if defined(MBED_TEST_MODE) + const advembsof::TaskLogger& getTaskLogger(); +#endif // defined(MBED_TEST_MODE) + + private: + // private methods + void init(); + void onReset(); + void gearTask(); + void speedDistanceTask(); + void temperatureTask(); + void resetTask(); + void displayTask1(); + void displayTask2(); + void cpuTask(); + + // stop flag, used for stopping the super-loop (set in stop()) + bool _stopFlag = false; + + std::chrono::microseconds _resetTime = std::chrono::microseconds::zero(); + volatile bool _resetFlag = false; + + // timer instance used for loggint task time and used by ResetDevice + Timer _timer; + // data member that represents the device for manipulating the gear + GearDevice _gearDevice; + uint8_t _currentGear = bike_computer::kMinGear; + uint8_t _currentGearSize = bike_computer::kMinGearSize; + // data member that represents the device for manipulating the pedal rotation + // speed/time + PedalDevice _pedalDevice; + 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 static_scheduling \ No newline at end of file diff --git a/static_scheduling_with_event/gear_device.cpp b/static_scheduling_with_event/gear_device.cpp new file mode 100644 index 0000000..4c30525 --- /dev/null +++ b/static_scheduling_with_event/gear_device.cpp @@ -0,0 +1,69 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief Gear Device implementation (static scheduling) + * + * @date 2023-11-17 + * @version 1.1.0 + ***************************************************************************/ + +#include "gear_device.hpp" + +// from disco_h747i/wrappers +#include + +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "GearDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling_with_event { + + +GearDevice::GearDevice() { + disco::Joystick::getInstance().setUpCallback( + 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::getCurrentGearSize() const { + return bike_computer::kMaxGearSize - core_util_atomic_load_u8(&_currentGear); +} + +void GearDevice::onUp() { + if (_currentGear < bike_computer::kMaxGear) { + core_util_atomic_incr_u8(&_currentGear, 1); + } +} + +void GearDevice::onDown() { + if (_currentGear > bike_computer::kMinGear) { + core_util_atomic_decr_u8(&_currentGear, 1); + } +} + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling_with_event/gear_device.hpp b/static_scheduling_with_event/gear_device.hpp new file mode 100644 index 0000000..250857a --- /dev/null +++ b/static_scheduling_with_event/gear_device.hpp @@ -0,0 +1,54 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief Gear Device header file (static scheduling) + * + * @date 2023-11-17 + * @version 1.1.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace static_scheduling_with_event { + +class GearDevice { + public: + explicit GearDevice(); // NOLINT(runtime/references) + + // make the class non copyable + GearDevice(GearDevice&) = delete; + GearDevice& operator=(GearDevice&) = delete; + + // method called for updating the bike system + uint8_t getCurrentGear(); + uint8_t getCurrentGearSize() const; + + void onUp(); + void onDown(); + + private: + // data members + volatile uint8_t _currentGear = bike_computer::kMinGear; +}; + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling_with_event/pedal_device.cpp b/static_scheduling_with_event/pedal_device.cpp new file mode 100644 index 0000000..97e9637 --- /dev/null +++ b/static_scheduling_with_event/pedal_device.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +* @file pedal_device.cpp +* @author Rémi Heredero +* @author Yann Sierro +* +* @brief Pedal Device implementation (static scheduling) +* @date 2024-11-17 +* @version 1.1.0 +****************************************************************************/ + +#include "pedal_device.hpp" + +// from disco_h747i/wrappers +#include + +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "PedalDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling_with_event { + + PedalDevice::PedalDevice() { + disco::Joystick::getInstance().setLeftCallback( + callback(this, &PedalDevice::onLeft) + ); + 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() { + uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); + if (currentStep > 0) { + 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(); + } + +} diff --git a/static_scheduling_with_event/pedal_device.hpp b/static_scheduling_with_event/pedal_device.hpp new file mode 100644 index 0000000..91104d4 --- /dev/null +++ b/static_scheduling_with_event/pedal_device.hpp @@ -0,0 +1,60 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief Pedal System header file (static scheduling) + * + * @date 2023-11-17 + * @version 1.1.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace static_scheduling_with_event { + +class PedalDevice { + public: + PedalDevice(); // NOLINT(runtime/references) + + // make the class non copyable + PedalDevice(PedalDevice&) = delete; + PedalDevice& operator=(PedalDevice&) = delete; + + // method called for updating the bike system + std::chrono::milliseconds getCurrentRotationTime(); + + private: + // private methods + void onLeft(); + void onRight(); + void increaseRotationSpeed(); + void decreaseRotationSpeed(); + + // data members + volatile uint32_t _currentStep = static_cast( + ( + bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime + ).count() / bike_computer::kDeltaPedalRotationTime.count() + ); +}; + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling_with_event/reset_device.cpp b/static_scheduling_with_event/reset_device.cpp new file mode 100644 index 0000000..9d7a2e6 --- /dev/null +++ b/static_scheduling_with_event/reset_device.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +* @file reset_device.cpp +* @author Rémi Heredero +* @author Yann Sierro +* +* @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 + +#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 static_scheduling_with_event { + + ResetDevice::ResetDevice(Callback cb) : _resetButton(PUSH_BUTTON) { + _resetButton.fall(cb); + } + + +} \ No newline at end of file diff --git a/static_scheduling_with_event/reset_device.hpp b/static_scheduling_with_event/reset_device.hpp new file mode 100644 index 0000000..8a10171 --- /dev/null +++ b/static_scheduling_with_event/reset_device.hpp @@ -0,0 +1,48 @@ +// 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 + * @author Rémi Heredero + * @author Yann Sierro + * + * @brief ResetDevice header file (static scheduling with event) + * + * @date 2023-11-17 + * @version 1.1.0 + ***************************************************************************/ + +#pragma once + +#include "mbed.h" + +namespace static_scheduling_with_event { + +class ResetDevice { + public: + explicit ResetDevice(Callback 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 static_scheduling \ No newline at end of file From 62d7d7b37684c447786cbef199767bf196072887 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 08:36:49 +0100 Subject: [PATCH 25/30] FIX Static scheduling with event --- TESTS/bike-computer/bike-system/main.cpp | 2 +- static_scheduling_with_event/bike_system.cpp | 42 -------------------- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/TESTS/bike-computer/bike-system/main.cpp b/TESTS/bike-computer/bike-system/main.cpp index e173b9a..2665b18 100644 --- a/TESTS/bike-computer/bike-system/main.cpp +++ b/TESTS/bike-computer/bike-system/main.cpp @@ -150,7 +150,7 @@ static utest::v1::status_t greentea_setup(const size_t number_of_cases) { // List of test cases in this file 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 queue", test_bike_system_event_queue), Case("test bike system with event handling", test_bike_system_with_event), }; diff --git a/static_scheduling_with_event/bike_system.cpp b/static_scheduling_with_event/bike_system.cpp index b97a0b3..c9eb1e3 100644 --- a/static_scheduling_with_event/bike_system.cpp +++ b/static_scheduling_with_event/bike_system.cpp @@ -75,48 +75,6 @@ BikeSystem::BikeSystem() : } void BikeSystem::start() { - tr_info("Starting Super-Loop without event handling"); - - init(); - - while (true) { - auto startTime = _timer.elapsed_time(); - - gearTask(); // 100ms : 0ms -> 100ms - speedDistanceTask(); // 200ms : 100ms -> 300ms - displayTask1(); // 200ms : 300ms -> 500ms - speedDistanceTask(); // 200ms : 500ms -> 700ms - resetTask(); // 100ms : 700ms -> 800ms - gearTask(); // 100ms : 800ms -> 900ms - speedDistanceTask(); // 200ms : 900ms -> 1100ms - temperatureTask(); // 100ms : 1100ms -> 1200ms - displayTask2(); // 100ms : 1200ms -> 1300ms - speedDistanceTask(); // 200ms : 1300ms -> 1500ms - resetTask(); // 100ms : 1500ms -> 1600ms - - - - // register the time at the end of the cyclic schedule period and print the - // elapsed time for the period - std::chrono::microseconds endTime = _timer.elapsed_time(); - const auto cycle = - std::chrono::duration_cast(endTime - startTime); - tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count()); - - bool stopFlag = false; - core_util_atomic_load(&stopFlag); - if (stopFlag) { - break; - } - - #if !defined(MBED_TEST_MODE) - _cpuLogger.printStats(); - #endif - - } -} - -void BikeSystem::startWithEventQueue() { tr_info("Starting Super-Loop with event handling"); From 20406664c39bd5597a4e24134decf263c2384a5e Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 09:13:18 +0100 Subject: [PATCH 26/30] FIX reset task --- static_scheduling_with_event/bike_system.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/static_scheduling_with_event/bike_system.cpp b/static_scheduling_with_event/bike_system.cpp index c9eb1e3..0ea2f49 100644 --- a/static_scheduling_with_event/bike_system.cpp +++ b/static_scheduling_with_event/bike_system.cpp @@ -208,6 +208,8 @@ void BikeSystem::resetTask() { std::chrono::microseconds responseTime = _timer.elapsed_time() - _resetTime; tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); _speedometer.reset(); + + core_util_atomic_store_bool(&_resetFlag, false); } _taskLogger.logPeriodAndExecutionTime( From f6f3d59ef398ed66747e1b7bc0fea3df6edca556 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 09:14:00 +0100 Subject: [PATCH 27/30] ADD run configurations --- .mbedignore | 3 ++- README.md | 36 ++++++++++++++++++++++++++++++++++++ main.cpp | 8 +++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/.mbedignore b/.mbedignore index ef3cf8a..c7067d1 100644 --- a/.mbedignore +++ b/.mbedignore @@ -14,4 +14,5 @@ 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/* \ No newline at end of file +mbed-os/storage/kvstore/* +static_scheduling/* \ No newline at end of file diff --git a/README.md b/README.md index fbe9625..0e4c986 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,42 @@ Test sensor libraries : mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run ``` +## Run static scheduling +On `.mbedignore` put at the end of the file +``` +static_scheduling_with_event/* +``` + +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 : +``` +static_scheduling_with_event/* +``` + +On main.cpp include `"static_scheduling/bike_system.hpp"` and use : +```cpp +static_scheduling::BikeSystem bikeSystem; +bikeSystem.startWithEventQueue(); +``` + +## Run static scheduling with event scheduling +On `.mbedignore` put at the end of the file +``` +static_scheduling/* +``` + +On main.cpp include `"static_scheduling_with_event/bike_system.hpp"` and use : +```cpp +static_scheduling_with_event::BikeSystem bikeSystem; +bikeSystem.start(); +``` + # Some questions ## 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. diff --git a/main.cpp b/main.cpp index b9e8ed2..f8b2f75 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include "mbed.h" // NOLINT #include "mbed_trace.h" +//#include "static_scheduling/bike_system.hpp" #include "static_scheduling_with_event/bike_system.hpp" #if defined(MBED_CONF_MBED_TRACE_ENABLE) @@ -17,8 +18,13 @@ int main() { #if defined(MBED_CONF_MBED_TRACE_ENABLE) mbed_trace_init(); #endif + + // static_scheduling::BikeSystem bikeSystem; + // bikeSystem.start(); + // bikeSystem.startWithEventQueue(); + static_scheduling_with_event::BikeSystem bikeSystem; - bikeSystem.startWithEventQueue(); + bikeSystem.start(); } #endif // MBED_TEST_MODE From 86e033fe2f1639b65513f8337bb453c0e7c1eb4d Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 09:14:12 +0100 Subject: [PATCH 28/30] ADD answer to questions --- README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0e4c986..9fbad2c 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,26 @@ bikeSystem.start(); ``` # Some questions -## 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? +## 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. -## 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? -We can observe only a usage of 75% because the CPU is more on Idle with Thread sleep. \ No newline at end of file +## 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?` + +We can observe only a usage of 75% because the CPU is more on Idle with Thread sleep. + +## 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. + +## 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?` + +` - If you do not press long enough on the push button, the event may be missed and no reset happens.` + +`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. \ No newline at end of file From ac4067e5a4dc230e6ed0889018487b2349b447c8 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 09:18:27 +0100 Subject: [PATCH 29/30] RM folder ignore for tests --- .mbedignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.mbedignore b/.mbedignore index c7067d1..ef3cf8a 100644 --- a/.mbedignore +++ b/.mbedignore @@ -14,5 +14,4 @@ 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/* -static_scheduling/* \ No newline at end of file +mbed-os/storage/kvstore/* \ No newline at end of file From eeb88edba31ba6766ded89ccfcbdad83a144f1e5 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Mon, 18 Nov 2024 09:21:22 +0100 Subject: [PATCH 30/30] UPD CI workflow --- .github/workflows/build-test.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 00d3f8b..9b36f30 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,6 +1,6 @@ name: Build test application on: - pull_request: + push: jobs: build-cli-v1: @@ -14,11 +14,9 @@ jobs: target: [DISCO_H747I] profile: [debug] tests: [ - tests-simple-test-always-succeed, - tests-simple-test-test-ptr, - advdembsof_library-tests-sensors-hdc1000, tests-bike-computer-sensor-device, - tests-bike-computer-speedometer + tests-bike-computer-speedometer, + tests-bike-computer-bike-system, ]