diff --git a/multi_tasking/bike_system.cpp b/multi_tasking/bike_system.cpp index 3a10e41..078e4dc 100644 --- a/multi_tasking/bike_system.cpp +++ b/multi_tasking/bike_system.cpp @@ -62,15 +62,16 @@ static constexpr std::chrono::milliseconds kCPUTaskDelay = 0 static constexpr std::chrono::milliseconds kCPUTaskComputationTime = 0ms; BikeSystem::BikeSystem() - : _gearDevice(callback(this, &BikeSystem::onGearUp), - callback(this, &BikeSystem::onGearDown)), + : _gearDevice(&_mailGearDevice), _pedalDevice(&_mailPedalDevice), _resetDevice(callback(this, &BikeSystem::onReset)), _speedometer(_timer), _cpuLogger(_timer), _isrEventThread(osPriorityAboveNormal, OS_STACK_SIZE, nullptr, "ISR_Event"), _speedDistanceThread( - osPriorityNormal, OS_STACK_SIZE, nullptr, "Speed_distance_Task") {} + osPriorityNormal, OS_STACK_SIZE, nullptr, "Speed_distance_Task"), + _gearTaskThread(osPriorityNormal, OS_STACK_SIZE, nullptr, "Gear_Task") {} + #if defined(MBED_TEST_MODE) const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; } #endif // defined(MBED_TEST_MODE) @@ -96,16 +97,8 @@ void BikeSystem::init() { } void BikeSystem::start() { - tr_info("Starting Super-Loop with event handling"); - init(); - 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); @@ -134,7 +127,12 @@ void BikeSystem::start() { tr_error("Thread %s started with status %d", _isrEventThread.get_name(), status); } - // dispathc the main queue in the main thread + status = _gearTaskThread.start(callback(this, &BikeSystem::loop_gear_task)); + if (status != osOK) { + tr_error("Thread %s started with status %d", _gearTaskThread.get_name(), status); + } + + // dispatch the main queue in the main thread dispatch_events(); } @@ -146,19 +144,6 @@ void BikeSystem::onReset() { resetEvent.post(); } -void BikeSystem::onGearUp() { - _onGearUpTime = _timer.elapsed_time(); - Event gearUpEvent(&_isrEventQueue, callback(this, &BikeSystem::gearUpTask)); - gearUpEvent.post(); -} - -void BikeSystem::onGearDown() { - _onGearDownTime = _timer.elapsed_time(); - Event gearDownEvent(&_isrEventQueue, - callback(this, &BikeSystem::gearDownTask)); - gearDownEvent.post(); -} - // ISR thread functions void BikeSystem::resetTask() { @@ -166,7 +151,12 @@ void BikeSystem::resetTask() { std::chrono::microseconds responseTime = _timer.elapsed_time() - _resetTime; tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); + + // ENTER CRITICAL SECTION + _mutexSpeedometer.lock(); _speedometer.reset(); + _mutexSpeedometer.unlock(); + // END CRITICAL SECTION _taskLogger.logPeriodAndExecutionTime( _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); @@ -196,6 +186,7 @@ void BikeSystem::speedDistanceTask() { // ENTER CRITICAL SECTION _mutexSpeedometer.lock(); + tr_info("%d", getCurrentGearSize()); _speedometer.setGearSize(getCurrentGearSize()); _mutexSpeed.lock(); _currentSpeed = _speedometer.getCurrentSpeed(); @@ -210,47 +201,33 @@ void BikeSystem::speedDistanceTask() { _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime); } +/* Gear thread functions */ +void BikeSystem::gearTask() { + auto taskStartTime = _timer.elapsed_time(); + + uint8_t* currentGear = _mailGearDevice.try_get(); + + if (currentGear != nullptr) { + // ENTER CRITICAL SECTION + _mutexGear.lock(); + _currentGear = *currentGear; + _mutexGear.unlock(); + _mutexGearSize.lock(); + _currentGearSize = bike_computer::kMaxGearSize - *currentGear; + _mutexGearSize.unlock(); + // END CRITICAL SECTION + + osStatus status = _mailGearDevice.free(currentGear); + if (status != osOK) { + tr_error("free current step in the speed distance tasks doesn't work !"); + } + } + _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(); @@ -313,6 +290,13 @@ void BikeSystem::loop_speed_distance_task() { } } +void BikeSystem::loop_gear_task() { + tr_info("Start loop gear calculation"); + while (true) { + gearTask(); + } +} + uint8_t BikeSystem::getCurrentGear() { uint8_t currentGear; diff --git a/multi_tasking/bike_system.hpp b/multi_tasking/bike_system.hpp index 7031b10..507f1ba 100644 --- a/multi_tasking/bike_system.hpp +++ b/multi_tasking/bike_system.hpp @@ -63,6 +63,7 @@ class BikeSystem { private: // private methods void init(); + // Main Thread void temperatureTask(); void displayTask1(); @@ -71,24 +72,26 @@ class BikeSystem { // ISR Thread void onReset(); - void onGearUp(); - void onGearDown(); - void gearUpTask(); - void gearDownTask(); - void speedDistanceTask(); void resetTask(); - // + // gear Thread + void gearTask(); + + // Speed / Distance Thread + void speedDistanceTask(); + + // GETTER - SETTER uint8_t getCurrentGear(); uint8_t getCurrentGearSize(); uint32_t getCurrentSpeed(); uint32_t getCurrentDistance(); - void setCurrentGear(uint8_t gear); + // Thread functions void dispatch_isr_events(); void dispatch_events(); void loop_speed_distance_task(); + void loop_gear_task(); // timer instance used for loggint task time and used by ResetDevice std::chrono::microseconds _resetTime = std::chrono::microseconds::zero(); @@ -137,6 +140,7 @@ class BikeSystem { // Mail Mail _mailPedalDevice; + Mail _mailGearDevice; // mutex for shared resource Mutex _mutexGearSize; @@ -148,6 +152,7 @@ class BikeSystem { // Tread for isr events Thread _isrEventThread; Thread _speedDistanceThread; + Thread _gearTaskThread; }; } // namespace multi_tasking diff --git a/multi_tasking/gear_device.cpp b/multi_tasking/gear_device.cpp index 33acd54..c106e30 100644 --- a/multi_tasking/gear_device.cpp +++ b/multi_tasking/gear_device.cpp @@ -30,6 +30,7 @@ #include #include "joystick.hpp" +#include "mbed_atomic.h" #include "mbed_trace.h" #if MBED_CONF_MBED_TRACE_ENABLE @@ -38,9 +39,33 @@ namespace multi_tasking { -GearDevice::GearDevice(Callback cbOnUp, Callback cbOnDown) { - disco::Joystick::getInstance().setUpCallback(callback(cbOnUp)); - disco::Joystick::getInstance().setDownCallback(callback(cbOnDown)); +GearDevice::GearDevice(Mail* mailBox) { + disco::Joystick::getInstance().setUpCallback(callback(this, &GearDevice::onUp)); + disco::Joystick::getInstance().setDownCallback(callback(this, &GearDevice::onDown)); + + _mailBox = mailBox; +} + +void GearDevice::onUp() { + if (_currentGear < bike_computer::kMaxGear) { + core_util_atomic_incr_u8(&_currentGear, 1); + sendMail(core_util_atomic_load_u8(&_currentGear)); + } +} + +void GearDevice::onDown() { + if (_currentGear > bike_computer::kMinGear) { + core_util_atomic_decr_u8(&_currentGear, 1); + sendMail(core_util_atomic_load_u8(&_currentGear)); + } +} + +void GearDevice::sendMail(uint32_t data) { + uint8_t* currentGear = _mailBox->try_alloc(); + if (currentGear != nullptr) { + *currentGear = data; + _mailBox->put(currentGear); + } } } // namespace multi_tasking diff --git a/multi_tasking/gear_device.hpp b/multi_tasking/gear_device.hpp index 4ff6cb1..334be15 100644 --- a/multi_tasking/gear_device.hpp +++ b/multi_tasking/gear_device.hpp @@ -26,20 +26,29 @@ #pragma once +#include "common/constants.hpp" #include "mbed.h" namespace multi_tasking { class GearDevice { public: - GearDevice(Callback cbOnUp, - Callback cbOnDown); // NOLINT(runtime/references) + explicit GearDevice(Mail* mailBox); // NOLINT(runtime/references) // make the class non copyable GearDevice(GearDevice&) = delete; GearDevice& operator=(GearDevice&) = delete; // method called for updating the bike system + void onUp(); + void onDown(); + + void sendMail(uint32_t data); + + private: + // data members + volatile uint8_t _currentGear = bike_computer::kMinGear; + Mail* _mailBox; }; } // namespace multi_tasking