From 95e92e256436d15c21d2a8659d8629e41975e0f3 Mon Sep 17 00:00:00 2001 From: fastium Date: Fri, 3 Jan 2025 17:10:42 +0100 Subject: [PATCH] ADD mail box for pedal device --- .pre-commit-config.yaml | 2 +- multi_tasking/bike_system.cpp | 276 ++++++++++++++++++++------------- multi_tasking/bike_system.hpp | 30 ++-- multi_tasking/pedal_device.cpp | 30 +++- multi_tasking/pedal_device.hpp | 14 +- 5 files changed, 227 insertions(+), 125 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index edf10e4..d935e1f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,5 +22,5 @@ repos: - id: cppcheck name: cppcheck require_serial: true - entry: cppcheck --enable=all --suppress=missingInclude --suppress=missingIncludeSystem --suppress=unusedFunction --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1 + entry: cppcheck --enable=all --suppress=missingInclude --suppress=missingIncludeSystem --suppress=unusedFunction --suppress=unusedStructMember --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1 language: system diff --git a/multi_tasking/bike_system.cpp b/multi_tasking/bike_system.cpp index a50fa00..3a10e41 100644 --- a/multi_tasking/bike_system.cpp +++ b/multi_tasking/bike_system.cpp @@ -28,9 +28,11 @@ #include +#include "Callback.h" #include "cmsis_os2.h" #include "constants.hpp" #include "mbed_trace.h" +#include "pedal_device.hpp" #if MBED_CONF_MBED_TRACE_ENABLE #define TRACE_GROUP "BikeSystem" #endif // MBED_CONF_MBED_TRACE_ENABLE @@ -62,11 +64,36 @@ static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 0 BikeSystem::BikeSystem() : _gearDevice(callback(this, &BikeSystem::onGearUp), callback(this, &BikeSystem::onGearDown)), - _pedalDevice(), + _pedalDevice(&_mailPedalDevice), _resetDevice(callback(this, &BikeSystem::onReset)), _speedometer(_timer), _cpuLogger(_timer), - _isrEventThread(osPriorityAboveNormal, OS_STACK_SIZE, nullptr, "ISR_Event") {} + _isrEventThread(osPriorityAboveNormal, OS_STACK_SIZE, nullptr, "ISR_Event"), + _speedDistanceThread( + osPriorityNormal, OS_STACK_SIZE, nullptr, "Speed_distance_Task") {} +#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("Ffalseailed to initialized the lcd display: %ld", 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(false); +} void BikeSystem::start() { tr_info("Starting Super-Loop with event handling"); @@ -101,9 +128,18 @@ void BikeSystem::start() { tr_error("Thread %s started with status %d", _isrEventThread.get_name(), status); } + status = + _speedDistanceThread.start(callback(this, &BikeSystem::loop_speed_distance_task)); + if (status != osOK) { + tr_error("Thread %s started with status %d", _isrEventThread.get_name(), status); + } + + // dispathc the main queue in the main thread dispatch_events(); } +/* Callback from isr */ + void BikeSystem::onReset() { _resetTime = _timer.elapsed_time(); Event resetEvent(&_isrEventQueue, callback(this, &BikeSystem::resetTask)); @@ -123,100 +159,7 @@ void BikeSystem::onGearDown() { gearDownEvent.post(); } -#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("Ffalseailed to initialized the lcd display: %ld", 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(false); -} - -void BikeSystem::gearUpTask() { - auto taskStartTime = _timer.elapsed_time(); - std::chrono::microseconds responseTime = _timer.elapsed_time() - _onGearUpTime; - tr_info("Gear up task: response time is %" PRIu64 " usecs", responseTime.count()); - - // CRITICAL SECTION - mutexGear.lock(); - if (_currentGear < bike_computer::kMaxGear) { - _currentGear++; - mutexGearSize.lock(); - _currentGearSize = bike_computer::kMaxGearSize - _currentGear; - mutexGearSize.unlock(); - } - mutexGear.unlock(); - // END CRITICAL SECTION - - _taskLogger.logPeriodAndExecutionTime( - _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); -} -void BikeSystem::gearDownTask() { - auto taskStartTime = _timer.elapsed_time(); - std::chrono::microseconds responseTime = _timer.elapsed_time() - _onGearDownTime; - tr_info("Gear down task: response time is %" PRIu64 " usecs", responseTime.count()); - - // CRITICAL SECTION - mutexGear.lock(); - if (_currentGear > bike_computer::kMinGear) { - _currentGear--; - mutexGearSize.lock(); - _currentGearSize = bike_computer::kMaxGearSize - _currentGear; - mutexGearSize.unlock(); - } - mutexGear.unlock(); - // END CRITICAL SECTION - - _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(getCurrentGearSize()); - - _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); -} +// ISR thread functions void BikeSystem::resetTask() { auto taskStartTime = _timer.elapsed_time(); @@ -229,12 +172,106 @@ void BikeSystem::resetTask() { _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); } +// Speed distance thread functions + +void BikeSystem::speedDistanceTask() { + auto taskStartTime = _timer.elapsed_time(); + + uint32_t* currentStep = _mailPedalDevice.try_get(); + + if (currentStep != nullptr) { + const auto pedalRotationTime = PedalDevice::getCurrentRotationTime(*currentStep); + + osStatus status = _mailPedalDevice.free(currentStep); + if (status != osOK) { + tr_error("free current step in the speed distance tasks doesn't work !"); + } + + // ENTER CRITICAL SECTION + _mutexSpeedometer.lock(); + _speedometer.setCurrentRotationTime(pedalRotationTime); + _mutexSpeedometer.unlock(); + // END CRITICAL SECTION + } + + // ENTER CRITICAL SECTION + _mutexSpeedometer.lock(); + _speedometer.setGearSize(getCurrentGearSize()); + _mutexSpeed.lock(); + _currentSpeed = _speedometer.getCurrentSpeed(); + _mutexSpeed.unlock(); + _mutexDistance.lock(); + _traveledDistance = _speedometer.getDistance(); + _mutexDistance.unlock(); + _mutexSpeedometer.unlock(); + // END CRITICAL SECTION + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); +} + +/* Main thread functions */ + +void BikeSystem::gearUpTask() { + auto taskStartTime = _timer.elapsed_time(); + std::chrono::microseconds responseTime = _timer.elapsed_time() - _onGearUpTime; + tr_info("Gear up task: response time is %" PRIu64 " usecs", responseTime.count()); + + // ENTER CRITICAL SECTION + _mutexGear.lock(); + if (_currentGear < bike_computer::kMaxGear) { + _currentGear++; + _mutexGearSize.lock(); + _currentGearSize = bike_computer::kMaxGearSize - _currentGear; + _mutexGearSize.unlock(); + } + _mutexGear.unlock(); + // END CRITICAL SECTION + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); +} +void BikeSystem::gearDownTask() { + auto taskStartTime = _timer.elapsed_time(); + std::chrono::microseconds responseTime = _timer.elapsed_time() - _onGearDownTime; + tr_info("Gear down task: response time is %" PRIu64 " usecs", responseTime.count()); + + // ENTER CRITICAL SECTION + _mutexGear.lock(); + if (_currentGear > bike_computer::kMinGear) { + _currentGear--; + _mutexGearSize.lock(); + _currentGearSize = bike_computer::kMaxGearSize - _currentGear; + _mutexGearSize.unlock(); + } + _mutexGear.unlock(); + // END CRITICAL SECTION + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime); +} + +void BikeSystem::temperatureTask() { + auto taskStartTime = _timer.elapsed_time(); + + // no need to protect access to data members (single threaded) + _currentTemperature = _sensorDevice.readTemperature(); + + ThisThread::sleep_for(std::chrono::duration_cast( + kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime))); + + _taskLogger.logPeriodAndExecutionTime( + _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); +} + void BikeSystem::displayTask1() { auto taskStartTime = _timer.elapsed_time(); + // ENTER CRITICAL SECTION _displayDevice.displayGear(getCurrentGear()); - _displayDevice.displaySpeed(_currentSpeed); - _displayDevice.displayDistance(_traveledDistance); + _displayDevice.displaySpeed(getCurrentSpeed()); + _displayDevice.displayDistance(getCurrentDistance()); + // END CRITICAL SECTION ThisThread::sleep_for(std::chrono::duration_cast( kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime))); @@ -269,13 +306,20 @@ void BikeSystem::dispatch_events() { tr_info("Stop dispatching main events"); } +void BikeSystem::loop_speed_distance_task() { + tr_info("Start loop speed-distance calculation"); + while (true) { + speedDistanceTask(); + } +} + uint8_t BikeSystem::getCurrentGear() { uint8_t currentGear; - // CRITICAL SECTION - mutexGear.lock(); + // ENTER CRITICAL SECTION + _mutexGear.lock(); currentGear = _currentGear; - mutexGear.unlock(); + _mutexGear.unlock(); // END CRITICAL SECTION return currentGear; @@ -284,13 +328,37 @@ uint8_t BikeSystem::getCurrentGear() { uint8_t BikeSystem::getCurrentGearSize() { uint8_t currentGearSize; - // CRITICAL SECTION - mutexGearSize.lock(); + // ENTER CRITICAL SECTION + _mutexGearSize.lock(); currentGearSize = _currentGearSize; - mutexGearSize.unlock(); + _mutexGearSize.unlock(); // END CRITICAL SECTION return currentGearSize; } +uint32_t BikeSystem::getCurrentSpeed() { + uint32_t currentSpeed; + + // ENTER CRITICAL SECTION + _mutexSpeed.lock(); + currentSpeed = _currentSpeed; + _mutexSpeed.unlock(); + // END CRITICAL SECTION + + return currentSpeed; +} + +uint32_t BikeSystem::getCurrentDistance() { + uint32_t currentDistance; + + // ENTER CRITICAL SECTION + _mutexDistance.lock(); + currentDistance = _traveledDistance; + _mutexDistance.unlock(); + // END CRITICAL SECTION + + return currentDistance; +} + } // namespace multi_tasking diff --git a/multi_tasking/bike_system.hpp b/multi_tasking/bike_system.hpp index 19b449f..7031b10 100644 --- a/multi_tasking/bike_system.hpp +++ b/multi_tasking/bike_system.hpp @@ -53,9 +53,6 @@ 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(); @@ -66,24 +63,32 @@ class BikeSystem { private: // private methods void init(); + // Main Thread + void temperatureTask(); + void displayTask1(); + void displayTask2(); + void cpuTask(); + + // ISR Thread void onReset(); void onGearUp(); void onGearDown(); void gearUpTask(); void gearDownTask(); void speedDistanceTask(); - void temperatureTask(); void resetTask(); - void displayTask1(); - void displayTask2(); - void cpuTask(); + // uint8_t getCurrentGear(); uint8_t getCurrentGearSize(); + uint32_t getCurrentSpeed(); + uint32_t getCurrentDistance(); + void setCurrentGear(uint8_t gear); void dispatch_isr_events(); void dispatch_events(); + void loop_speed_distance_task(); // timer instance used for loggint task time and used by ResetDevice std::chrono::microseconds _resetTime = std::chrono::microseconds::zero(); @@ -130,12 +135,19 @@ class BikeSystem { EventQueue _isrEventQueue; EventQueue _eventQueue; + // Mail + Mail _mailPedalDevice; + // mutex for shared resource - Mutex mutexGearSize; - Mutex mutexGear; + Mutex _mutexGearSize; + Mutex _mutexGear; + Mutex _mutexSpeed; + Mutex _mutexDistance; + Mutex _mutexSpeedometer; // Tread for isr events Thread _isrEventThread; + Thread _speedDistanceThread; }; } // namespace multi_tasking diff --git a/multi_tasking/pedal_device.cpp b/multi_tasking/pedal_device.cpp index 06ecdb5..02e3133 100644 --- a/multi_tasking/pedal_device.cpp +++ b/multi_tasking/pedal_device.cpp @@ -36,21 +36,19 @@ namespace multi_tasking { -PedalDevice::PedalDevice(Callback cbOnLeft, Callback cbOnRight) { - disco::Joystick::getInstance().setLeftCallback(callback(cbOnLeft)); - disco::Joystick::getInstance().setRightCallback(callback(cbOnRight)); -} +PedalDevice::PedalDevice(Mail* mailBox) { + 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; + _mailBox = mailBox; } void PedalDevice::increaseRotationSpeed() { uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); if (currentStep > 0) { core_util_atomic_decr_u32(&_currentStep, 1); + sendMail(--currentStep); } } @@ -58,6 +56,7 @@ void PedalDevice::decreaseRotationSpeed() { uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); if (currentStep < bike_computer::kNbrOfSteps) { core_util_atomic_incr_u32(&_currentStep, 1); + sendMail(++currentStep); } } @@ -65,4 +64,19 @@ void PedalDevice::onLeft() { decreaseRotationSpeed(); } void PedalDevice::onRight() { increaseRotationSpeed(); } +void PedalDevice::sendMail(uint32_t data) { + uint32_t* currentStep = _mailBox->try_alloc(); + if (currentStep != nullptr) { + *currentStep = data; + (*_mailBox).put(currentStep); + } +} + +// mbed_build_and_runstatic methods + +std::chrono::milliseconds PedalDevice::getCurrentRotationTime(uint32_t step) { + return bike_computer::kMinPedalRotationTime + + step * bike_computer::kDeltaPedalRotationTime; +} + } // namespace multi_tasking diff --git a/multi_tasking/pedal_device.hpp b/multi_tasking/pedal_device.hpp index 8787548..19cb3fb 100644 --- a/multi_tasking/pedal_device.hpp +++ b/multi_tasking/pedal_device.hpp @@ -33,22 +33,30 @@ namespace multi_tasking { class PedalDevice { public: - PedalDevice(Callback cbOnLeft, - Callback cbOnRight); // NOLINT(runtime/references) + explicit PedalDevice(Mail* mailBox); // 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(); + static std::chrono::milliseconds getCurrentRotationTime(uint32_t step); private: + // private methods + void onLeft(); + void onRight(); + void increaseRotationSpeed(); + void decreaseRotationSpeed(); + + void sendMail(uint32_t data); // data members volatile uint32_t _currentStep = static_cast( (bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime) .count() / bike_computer::kDeltaPedalRotationTime.count()); + + Mail* _mailBox; }; } // namespace multi_tasking