From c193de14a917ff1b8c1efba7254e6f14bdf3f08a Mon Sep 17 00:00:00 2001 From: RedHawk Date: Sat, 13 May 2023 01:40:31 +0300 Subject: [PATCH 1/6] logging: Added timestamp and function to logging. --- source/shoh/src/main.cpp | 5 +++-- source/shoh/src/threads/logging/Log.h | 18 +++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/source/shoh/src/main.cpp b/source/shoh/src/main.cpp index f054cb4..830b548 100644 --- a/source/shoh/src/main.cpp +++ b/source/shoh/src/main.cpp @@ -37,8 +37,9 @@ extern "C" { Chip_SCT_Init (LPC_SCT1); LPC_SCT1->CONFIG = SCT_CONFIG_32BIT_COUNTER; - LPC_SCT1->CTRL_U = SCT_CTRL_PRE_L (255) - | SCT_CTRL_CLRCTR_L; // set prescaler to 256 (255 + + //LPC_SCT1->CTRL_U = SCT_CTRL_PRE_L (255) + // | SCT_CTRL_CLRCTR_L; // set prescaler to 256 (255 + // 1), and start timer + LPC_SCT1->CTRL_U = SCT_CTRL_CLRCTR_L; } } diff --git a/source/shoh/src/threads/logging/Log.h b/source/shoh/src/threads/logging/Log.h index 9c64851..4f80c00 100644 --- a/source/shoh/src/threads/logging/Log.h +++ b/source/shoh/src/threads/logging/Log.h @@ -46,8 +46,10 @@ extern QueueHandle_t logging_queue; xQueueSend(logging_queue, (void*)message, portMAX_DELAY); \ } -static void create_log_line(const char * _status, +static void create_log_line(const size_t _timestamp, + const char * _status, const char * _location, + const char * _func, const size_t _line, const char * _fmt, ...) { @@ -58,9 +60,11 @@ static void create_log_line(const char * _status, va_end(args); char buffer [LOG_BUFFER_MAX_CAP] = {0}; int buffer_len = snprintf(buffer, LOG_BUFFER_MAX_CAP, - "[%s] [File: %s] [Line: %d] %.*s", + "[%zu]:[%s] In [File: %s] [Func: %s] [Line: %zu]\r\n %.*s", + _timestamp, _status, _location, + _func, _line, message_len, message); @@ -68,18 +72,18 @@ static void create_log_line(const char * _status, } -#define LOG_INFO(fmt, ...) \ - create_log_line(C_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__); +#define LOG_INFO( fmt, ...) \ + create_log_line(LPC_SCT1->COUNT_U, C_INFO, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #define LOG_WARNING(fmt, ...) \ - create_log_line(C_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(LPC_SCT1->COUNT_U, C_WARN, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #define LOG_ERROR(fmt, ...) \ - create_log_line(C_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(LPC_SCT1->COUNT_U, C_ERROR, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #if LOG_DEBUG_MESSAGES #define LOG_DEBUG(fmt, ...) \ - create_log_line(C_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(LPC_SCT1->COUNT_U, C_DEBUG, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #else #define LOG_DEBUG(fmt, ...) #endif From cd097d78838dcc3880d5b90636e26adfaf01287c Mon Sep 17 00:00:00 2001 From: RedHawk Date: Sun, 14 May 2023 16:20:46 +0300 Subject: [PATCH 2/6] logging: Base for Clock. *Doesn't work, yet. --- source/shoh/src/main.cpp | 14 --- source/shoh/src/peripherals/Clock.cpp | 129 ++++++++++++++++++++++ source/shoh/src/peripherals/Clock.h | 36 ++++++ source/shoh/src/threads/logging/Log.h | 20 ++-- source/shoh/src/threads/master/Master.cpp | 11 +- source/shoh/src/threads/master/Master.h | 2 +- 6 files changed, 188 insertions(+), 24 deletions(-) create mode 100644 source/shoh/src/peripherals/Clock.cpp create mode 100644 source/shoh/src/peripherals/Clock.h diff --git a/source/shoh/src/main.cpp b/source/shoh/src/main.cpp index 830b548..8495385 100644 --- a/source/shoh/src/main.cpp +++ b/source/shoh/src/main.cpp @@ -29,17 +29,3 @@ int main(void) return 1; } - -extern "C" -{ - void - vConfigureTimerForRunTimeStats (void) - { - Chip_SCT_Init (LPC_SCT1); - LPC_SCT1->CONFIG = SCT_CONFIG_32BIT_COUNTER; - //LPC_SCT1->CTRL_U = SCT_CTRL_PRE_L (255) - // | SCT_CTRL_CLRCTR_L; // set prescaler to 256 (255 + - // 1), and start timer - LPC_SCT1->CTRL_U = SCT_CTRL_CLRCTR_L; - } -} diff --git a/source/shoh/src/peripherals/Clock.cpp b/source/shoh/src/peripherals/Clock.cpp new file mode 100644 index 0000000..a6c0efa --- /dev/null +++ b/source/shoh/src/peripherals/Clock.cpp @@ -0,0 +1,129 @@ +/* + * Clock.cpp + * + * Created on: 14 May 2023 + */ + +#include "Clock.h" +#include "FreeRTOS.h" +#include "task.h" + +static uint64_t counter_overflows = 0; + +extern "C" { + /** + * @brief Interrupt is used by the Clock class to monitor + * the time elapsed since the start. + * It triggers on counter overflow. + */ + void SCT0_1_IRQHandler (void) + { + counter_overflows++; + portBASE_TYPE xHigherPriorityWoken = pdFALSE; + Chip_SCT_ClearEventFlag(LPC_SCT1, SCT_EVT_0); + portEND_SWITCHING_ISR(xHigherPriorityWoken); + } +} + +/** + * @brief Construct a new Clock:: Clock object + * @attention Should be initialised by the first task as early as possible. + * _overflows(1) is important, since there is a starting overflow. + */ +Clock::Clock() : _raw_time(0), _overflows(1) {} + +Clock::~Clock() {} + +/** + * @brief Handles counter overflows and updates clock value. + * Time difference between updateClock() calls should not be overly + * large, if it will be enough to get overflow amount of overflows + * 2 times between the function calls the clock will desync. + * *Barely possible with counter overflows every 89 sec, but still. + */ +void Clock::updateClock() +{ + int64_t diff = 0; + //Remember old number of overflows. + int64_t old_overflows = this->_overflows; + //Capture number of counter overflows. + this->_overflows = counter_overflows; + + //Handle overflows. + diff = (old_overflows <= this->_overflows) + ? (this->_overflows - old_overflows) + : (0xffffffffffffffff - old_overflows + this->_overflows + 1); + _raw_time += (double)((double)diff * (uint32_t)0xffffffff + LPC_SCT1->COUNT_U) * 1000 + / (double)(Chip_Clock_GetMainClockRate()); +} + +TimeFromStart Clock::getTimeFromStart() +{ + this->updateClock(); + return this->convertToTimeFromStart(this->_raw_time); +} + +TimeFromStart Clock::convertToTimeFromStart(double raw_time) +{ + //The convertion is slow, but reliable. + TimeFromStart tfs; + tfs.days = raw_time / 86400000; + tfs.hours = raw_time / 3600000 - tfs.days * 24; //Can be ((long long int)raw_time % 86400000) + tfs.minutes = raw_time / 60000 - tfs.days * 1440 + - tfs.hours * 60; //Can be ((long long int)raw_time % 3600000) + tfs.seconds = raw_time / 1000 - tfs.days * 86400 + - tfs.hours * 3600 + - tfs.minutes * 60; //Can be ((long long int)raw_time % 60000) + tfs.milliseconds = raw_time - tfs.days * 86400000 + - tfs.hours * 3600000 + - tfs.minutes * 60000 + - tfs.seconds * 1000; //Can be ((long long int)raw_time % 1000) + return tfs; +} + +double Clock::getTimeFromStartRaw() +{ + this->updateClock(); + return this->_raw_time; +} + +double Clock::convertToTimeFromStartRaw(TimeFromStart tfs) +{ + return (double)(tfs.days * 86400000 + tfs.hours * 3600000 + + tfs.minutes * 60000 + + tfs.seconds * 1000 + + tfs.milliseconds); +} + +extern "C" +{ + /** + * @brief This function is used by FreeRTOS to configure the collection of + * time used by tasks. + * . + */ + void + vConfigureTimerForRunTimeStats (void) + { + Chip_SCT_Init (LPC_SCT1); + /* Sets match to trigger when all bits of counter are 1 */ + Chip_SCT_SetMatchCount(LPC_SCT1, SCT_MATCH_0, 0xffffffff); + /* Set corresponding match register to event */ + LPC_SCT1->EVENT[0].CTRL |= 0x1 | (0x1 << 12); + /* Enable event */ + LPC_SCT1->EVENT[0].STATE |= 0x1; + + /* Set the interrupt */ + Chip_SCT_EnableEventInt(LPC_SCT1, SCT_EVT_0); + + /* Clear timer of any pending interrupts */ + NVIC_ClearPendingIRQ(SCT0_1_IRQn); + + /* Enable timer interrupt */ + NVIC_EnableIRQ(SCT0_1_IRQn); + + /* Start timer */ + LPC_SCT1->CONFIG = SCT_CONFIG_32BIT_COUNTER; + LPC_SCT1->CTRL_U = SCT_CTRL_CLRCTR_L; + } +} diff --git a/source/shoh/src/peripherals/Clock.h b/source/shoh/src/peripherals/Clock.h new file mode 100644 index 0000000..356ff28 --- /dev/null +++ b/source/shoh/src/peripherals/Clock.h @@ -0,0 +1,36 @@ +/* + * Clock.h + * + * Created on: 14 May 2023 + */ + +#ifndef PERIPHERALS_CLOCK_H_ +#define PERIPHERALS_CLOCK_H_ + +#include "chip.h" + +struct TimeFromStart +{ + uint16_t days; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; + uint16_t milliseconds; +}; + + +class Clock { +public: + Clock(); + virtual ~Clock(); + void updateClock(); + TimeFromStart getTimeFromStart(); + TimeFromStart convertToTimeFromStart(double raw_time); + double getTimeFromStartRaw(); + double convertToTimeFromStartRaw(TimeFromStart tfs); +private: + double _raw_time; //ms + int64_t _overflows; +}; + +#endif /* PERIPHERALS_CLOCK_H_ */ diff --git a/source/shoh/src/threads/logging/Log.h b/source/shoh/src/threads/logging/Log.h index 4f80c00..def1d74 100644 --- a/source/shoh/src/threads/logging/Log.h +++ b/source/shoh/src/threads/logging/Log.h @@ -8,7 +8,9 @@ #include "FreeRTOS.h" #include "task.h" #include "queue.h" +#include "Clock.h" +extern Clock *global_clock; extern QueueHandle_t logging_queue; /* ================= Settings ================== */ @@ -46,7 +48,7 @@ extern QueueHandle_t logging_queue; xQueueSend(logging_queue, (void*)message, portMAX_DELAY); \ } -static void create_log_line(const size_t _timestamp, +static void create_log_line(const TimeFromStart _timestamp, const char * _status, const char * _location, const char * _func, @@ -60,8 +62,12 @@ static void create_log_line(const size_t _timestamp, va_end(args); char buffer [LOG_BUFFER_MAX_CAP] = {0}; int buffer_len = snprintf(buffer, LOG_BUFFER_MAX_CAP, - "[%zu]:[%s] In [File: %s] [Func: %s] [Line: %zu]\r\n %.*s", - _timestamp, + "[%02zu:%02zu:%02zu:%02zu:%03zu]:[%s] In [File: %s] [Func: %s] [Line: %zu]\r\n %.*s", + _timestamp.days, + _timestamp.hours, + _timestamp.minutes, + _timestamp.seconds, + _timestamp.milliseconds, _status, _location, _func, @@ -73,17 +79,17 @@ static void create_log_line(const size_t _timestamp, } #define LOG_INFO( fmt, ...) \ - create_log_line(LPC_SCT1->COUNT_U, C_INFO, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(global_clock->getTimeFromStart(), C_INFO, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #define LOG_WARNING(fmt, ...) \ - create_log_line(LPC_SCT1->COUNT_U, C_WARN, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(global_clock->getTimeFromStart(), C_WARN, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #define LOG_ERROR(fmt, ...) \ - create_log_line(LPC_SCT1->COUNT_U, C_ERROR, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(global_clock->getTimeFromStart(), C_ERROR, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #if LOG_DEBUG_MESSAGES #define LOG_DEBUG(fmt, ...) \ - create_log_line(LPC_SCT1->COUNT_U, C_DEBUG, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); + create_log_line(global_clock->getTimeFromStart(), C_DEBUG, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__); #else #define LOG_DEBUG(fmt, ...) #endif diff --git a/source/shoh/src/threads/master/Master.cpp b/source/shoh/src/threads/master/Master.cpp index 23d6536..98384c5 100644 --- a/source/shoh/src/threads/master/Master.cpp +++ b/source/shoh/src/threads/master/Master.cpp @@ -14,7 +14,6 @@ #include "Logging.h" #include "UserInterface.h" #include "queue.h" -#include "Logging.h" static const char* rotary_direction[] = { @@ -25,12 +24,18 @@ static const char* rotary_direction[] = }; QueueHandle_t logging_queue; +Clock *global_clock = new Clock(); Master::Master(ThreadCommon::QueueManager* qm) : _qm(qm) { LOG_DEBUG("Creating Master"); } +Master::~Master() +{ + LOG_ERROR("Master was deleted"); +} + void Master::HandleEventType(Event* e, Event::EventType type) { switch (type) @@ -40,6 +45,7 @@ void Master::HandleEventType(Event* e, Event::EventType type) case Event::Rotary: //Comes from rotary, goes to manager _qm->send(ThreadCommon::QueueManager::manager_event_master, e, 0); + //LOG_WARNING("Timestamp: %zus, Clock: %zu, Chip freq: %zu", LPC_SCT1->COUNT_U / Chip_Clock_GetMainClockRate(), LPC_SCT1->COUNT_U, Chip_Clock_GetMainClockRate()); LOG_DEBUG("Rotary: %s has been forwarded to manager", rotary_direction[e->getDataOf(type)]); break; case Event::InternalTemp: @@ -79,7 +85,8 @@ void Master::taskFunction() { { HandleEventType(&data, i); } - } + } + global_clock->updateClock(); } } diff --git a/source/shoh/src/threads/master/Master.h b/source/shoh/src/threads/master/Master.h index 14c44a0..8585c6b 100644 --- a/source/shoh/src/threads/master/Master.h +++ b/source/shoh/src/threads/master/Master.h @@ -20,7 +20,7 @@ class Master { public: Master(ThreadCommon::QueueManager* qm); - virtual ~Master() = default; + virtual ~Master(); void taskFunction(); private: From b5b54769b3cffd7a94415941ea445e59e9f25e53 Mon Sep 17 00:00:00 2001 From: RedHawk Date: Mon, 15 May 2023 00:25:17 +0300 Subject: [PATCH 3/6] clock: Figured out the working formula. *Now the counter works, but at what cost? *Joking, it has some holes that must be patched up though. --- source/shoh/src/peripherals/Clock.cpp | 26 ++++++++++++++++++++++---- source/shoh/src/peripherals/Clock.h | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/source/shoh/src/peripherals/Clock.cpp b/source/shoh/src/peripherals/Clock.cpp index a6c0efa..dd65934 100644 --- a/source/shoh/src/peripherals/Clock.cpp +++ b/source/shoh/src/peripherals/Clock.cpp @@ -30,7 +30,7 @@ extern "C" { * @attention Should be initialised by the first task as early as possible. * _overflows(1) is important, since there is a starting overflow. */ -Clock::Clock() : _raw_time(0), _overflows(1) {} +Clock::Clock() : _raw_time(0), _overflows(1), _last_counter_value(0) {} Clock::~Clock() {} @@ -46,15 +46,33 @@ void Clock::updateClock() int64_t diff = 0; //Remember old number of overflows. int64_t old_overflows = this->_overflows; + /* It would be nice to halt the counter for the next 2 lines. + Unless we are fine with rare 1-second errors. + */ //Capture number of counter overflows. this->_overflows = counter_overflows; - + //Capture the counter value. + uint32_t cur_count_u = LPC_SCT1->COUNT_U; + //Handle overflows. diff = (old_overflows <= this->_overflows) ? (this->_overflows - old_overflows) : (0xffffffffffffffff - old_overflows + this->_overflows + 1); - _raw_time += (double)((double)diff * (uint32_t)0xffffffff + LPC_SCT1->COUNT_U) * 1000 + + //Formula for getting elapsed milliseconds since the last function call. + //Multiply max counter value by the number of overflows. + _raw_time += (double)((double)diff * (uint32_t)0xffffffff + //Add full counter value if there are overflows. + //Add difference between 2 captured counter values otherwise. + + ((diff) ? cur_count_u : cur_count_u - this->_last_counter_value)) + //We need the value in milliseconds + * 1000 + //Divide it by the clock frequency. t = 1 / f / (double)(Chip_Clock_GetMainClockRate()); + + //Remember last counter value. + //It is important if we won't have an overflow next time. + this->_last_counter_value = LPC_SCT1->COUNT_U; } TimeFromStart Clock::getTimeFromStart() @@ -65,7 +83,7 @@ TimeFromStart Clock::getTimeFromStart() TimeFromStart Clock::convertToTimeFromStart(double raw_time) { - //The convertion is slow, but reliable. + //The conversion is slow, but reliable. TimeFromStart tfs; tfs.days = raw_time / 86400000; tfs.hours = raw_time / 3600000 - tfs.days * 24; //Can be ((long long int)raw_time % 86400000) diff --git a/source/shoh/src/peripherals/Clock.h b/source/shoh/src/peripherals/Clock.h index 356ff28..0ad7846 100644 --- a/source/shoh/src/peripherals/Clock.h +++ b/source/shoh/src/peripherals/Clock.h @@ -31,6 +31,7 @@ public: private: double _raw_time; //ms int64_t _overflows; + uint32_t _last_counter_value; }; #endif /* PERIPHERALS_CLOCK_H_ */ From 27487de4f90dd5087f0882874b4538a5a38e5f44 Mon Sep 17 00:00:00 2001 From: RedHawk Date: Mon, 15 May 2023 00:56:16 +0300 Subject: [PATCH 4/6] clock: Mutex, better names, stopping the counter. *Found a periodic bug with wrong time addition. (probably the overflow handling.) --- source/shoh/src/peripherals/Clock.cpp | 23 ++++++++++++++++------- source/shoh/src/peripherals/Clock.h | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/source/shoh/src/peripherals/Clock.cpp b/source/shoh/src/peripherals/Clock.cpp index dd65934..dae5c9a 100644 --- a/source/shoh/src/peripherals/Clock.cpp +++ b/source/shoh/src/peripherals/Clock.cpp @@ -43,28 +43,37 @@ Clock::~Clock() {} */ void Clock::updateClock() { - int64_t diff = 0; + int64_t diff_overflows = 0; //Remember old number of overflows. int64_t old_overflows = this->_overflows; - /* It would be nice to halt the counter for the next 2 lines. - Unless we are fine with rare 1-second errors. - */ + + this->_guard.lock(); + //Stop the counter. + Chip_SCT_SetControl(LPC_SCT1, 0x1 << 1); //Capture number of counter overflows. this->_overflows = counter_overflows; //Capture the counter value. uint32_t cur_count_u = LPC_SCT1->COUNT_U; + //Resume the counter. + Chip_SCT_ClearControl(LPC_SCT1, 0x1 << 1); + this->_guard.unlock(); //Handle overflows. - diff = (old_overflows <= this->_overflows) + diff_overflows = (old_overflows <= this->_overflows) + //Usually it is new amount of overflows - old. ? (this->_overflows - old_overflows) + //It is possible that overflows counter will overflow. : (0xffffffffffffffff - old_overflows + this->_overflows + 1); + // Bug + // Counts += 1 minute 30 seconds (90 seconds, 90000 ms) sometimes, while has to count 10 seconds (10000 ms) + //Formula for getting elapsed milliseconds since the last function call. //Multiply max counter value by the number of overflows. - _raw_time += (double)((double)diff * (uint32_t)0xffffffff + _raw_time += (double)((double)diff_overflows * (uint32_t)0xffffffff //Add full counter value if there are overflows. //Add difference between 2 captured counter values otherwise. - + ((diff) ? cur_count_u : cur_count_u - this->_last_counter_value)) + + ((diff_overflows) ? cur_count_u : cur_count_u - this->_last_counter_value)) //We need the value in milliseconds * 1000 //Divide it by the clock frequency. t = 1 / f diff --git a/source/shoh/src/peripherals/Clock.h b/source/shoh/src/peripherals/Clock.h index 0ad7846..046799e 100644 --- a/source/shoh/src/peripherals/Clock.h +++ b/source/shoh/src/peripherals/Clock.h @@ -8,6 +8,7 @@ #define PERIPHERALS_CLOCK_H_ #include "chip.h" +#include "Fmutex.h" struct TimeFromStart { @@ -32,6 +33,7 @@ private: double _raw_time; //ms int64_t _overflows; uint32_t _last_counter_value; + Fmutex _guard; }; #endif /* PERIPHERALS_CLOCK_H_ */ From bf43a7b285662051cf29454e028d7b38a7d62d08 Mon Sep 17 00:00:00 2001 From: RedHawk Date: Mon, 15 May 2023 11:26:40 +0300 Subject: [PATCH 5/6] clock: Fixed the formula --- source/shoh/src/peripherals/Clock.cpp | 44 ++++++++++++++++----------- source/shoh/src/peripherals/Clock.h | 4 +-- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/source/shoh/src/peripherals/Clock.cpp b/source/shoh/src/peripherals/Clock.cpp index dae5c9a..40d5faf 100644 --- a/source/shoh/src/peripherals/Clock.cpp +++ b/source/shoh/src/peripherals/Clock.cpp @@ -8,6 +8,8 @@ #include "FreeRTOS.h" #include "task.h" +#define MAX_COUNTER_VALUE (uint64_t)0xffffffff + static uint64_t counter_overflows = 0; extern "C" { @@ -43,9 +45,9 @@ Clock::~Clock() {} */ void Clock::updateClock() { - int64_t diff_overflows = 0; + uint64_t diff_overflows = 0; //Remember old number of overflows. - int64_t old_overflows = this->_overflows; + uint64_t old_overflows = this->_overflows; this->_guard.lock(); //Stop the counter. @@ -53,7 +55,7 @@ void Clock::updateClock() //Capture number of counter overflows. this->_overflows = counter_overflows; //Capture the counter value. - uint32_t cur_count_u = LPC_SCT1->COUNT_U; + uint64_t cur_count_u = LPC_SCT1->COUNT_U; //Resume the counter. Chip_SCT_ClearControl(LPC_SCT1, 0x1 << 1); this->_guard.unlock(); @@ -63,25 +65,31 @@ void Clock::updateClock() //Usually it is new amount of overflows - old. ? (this->_overflows - old_overflows) //It is possible that overflows counter will overflow. - : (0xffffffffffffffff - old_overflows + this->_overflows + 1); + : (0xffffffffffffffff - old_overflows + this->_overflows); - // Bug - // Counts += 1 minute 30 seconds (90 seconds, 90000 ms) sometimes, while has to count 10 seconds (10000 ms) - - //Formula for getting elapsed milliseconds since the last function call. - //Multiply max counter value by the number of overflows. - _raw_time += (double)((double)diff_overflows * (uint32_t)0xffffffff - //Add full counter value if there are overflows. - //Add difference between 2 captured counter values otherwise. - + ((diff_overflows) ? cur_count_u : cur_count_u - this->_last_counter_value)) - //We need the value in milliseconds - * 1000 - //Divide it by the clock frequency. t = 1 / f - / (double)(Chip_Clock_GetMainClockRate()); + //First case -> no overflow + if(!diff_overflows) + { + //Get the difference between values and convert to milliseconds. (t(ms) = 1000 / f) + _raw_time += (double)((cur_count_u - this->_last_counter_value) * 1000) + / (double)(Chip_Clock_GetMainClockRate()); + } + //Second case -> overflow + else + { + _raw_time += (double)( + //Add full counter values for all overflows except one. + (MAX_COUNTER_VALUE * (diff_overflows - 1) + //Add the difference between counter values having overflow in mind. + + (cur_count_u + (MAX_COUNTER_VALUE - _last_counter_value))) + //Convert to milliseconds. + * 1000) + / (double)(Chip_Clock_GetMainClockRate()); + } //Remember last counter value. //It is important if we won't have an overflow next time. - this->_last_counter_value = LPC_SCT1->COUNT_U; + this->_last_counter_value = cur_count_u; } TimeFromStart Clock::getTimeFromStart() diff --git a/source/shoh/src/peripherals/Clock.h b/source/shoh/src/peripherals/Clock.h index 046799e..5897ce4 100644 --- a/source/shoh/src/peripherals/Clock.h +++ b/source/shoh/src/peripherals/Clock.h @@ -31,8 +31,8 @@ public: double convertToTimeFromStartRaw(TimeFromStart tfs); private: double _raw_time; //ms - int64_t _overflows; - uint32_t _last_counter_value; + uint64_t _overflows; + uint64_t _last_counter_value; Fmutex _guard; }; From 24d116e9b8d3d46b190f154a9dfe7826a7e334f1 Mon Sep 17 00:00:00 2001 From: RedHawk Date: Mon, 15 May 2023 13:04:16 +0300 Subject: [PATCH 6/6] clock: A little cleanup. --- source/shoh/src/peripherals/Clock.cpp | 70 +++++++++++++-------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/source/shoh/src/peripherals/Clock.cpp b/source/shoh/src/peripherals/Clock.cpp index 40d5faf..6366182 100644 --- a/source/shoh/src/peripherals/Clock.cpp +++ b/source/shoh/src/peripherals/Clock.cpp @@ -8,7 +8,7 @@ #include "FreeRTOS.h" #include "task.h" -#define MAX_COUNTER_VALUE (uint64_t)0xffffffff +static const uint64_t max_counter_value = 0xffffffff; static uint64_t counter_overflows = 0; @@ -25,6 +25,35 @@ extern "C" { Chip_SCT_ClearEventFlag(LPC_SCT1, SCT_EVT_0); portEND_SWITCHING_ISR(xHigherPriorityWoken); } + + /** + * @brief This function is used by FreeRTOS to configure the collection of + * time used by tasks. + */ + void + vConfigureTimerForRunTimeStats (void) + { + Chip_SCT_Init (LPC_SCT1); + /* Sets match to trigger when all bits of counter are 1 */ + Chip_SCT_SetMatchCount(LPC_SCT1, SCT_MATCH_0, 0xffffffff); + /* Set corresponding match register to event */ + LPC_SCT1->EVENT[0].CTRL |= 0x1 | (0x1 << 12); + /* Enable event */ + LPC_SCT1->EVENT[0].STATE |= 0x1; + + /* Set the interrupt */ + Chip_SCT_EnableEventInt(LPC_SCT1, SCT_EVT_0); + + /* Clear timer of any pending interrupts */ + NVIC_ClearPendingIRQ(SCT0_1_IRQn); + + /* Enable timer interrupt */ + NVIC_EnableIRQ(SCT0_1_IRQn); + + /* Start timer */ + LPC_SCT1->CONFIG = SCT_CONFIG_32BIT_COUNTER; + LPC_SCT1->CTRL_U = SCT_CTRL_CLRCTR_L; + } } /** @@ -79,9 +108,9 @@ void Clock::updateClock() { _raw_time += (double)( //Add full counter values for all overflows except one. - (MAX_COUNTER_VALUE * (diff_overflows - 1) + (max_counter_value * (diff_overflows - 1) //Add the difference between counter values having overflow in mind. - + (cur_count_u + (MAX_COUNTER_VALUE - _last_counter_value))) + + (cur_count_u + (max_counter_value - _last_counter_value))) //Convert to milliseconds. * 1000) / (double)(Chip_Clock_GetMainClockRate()); @@ -122,43 +151,10 @@ double Clock::getTimeFromStartRaw() return this->_raw_time; } -double Clock::convertToTimeFromStartRaw(TimeFromStart tfs) +inline double Clock::convertToTimeFromStartRaw(TimeFromStart tfs) { return (double)(tfs.days * 86400000 + tfs.hours * 3600000 + tfs.minutes * 60000 + tfs.seconds * 1000 + tfs.milliseconds); } - -extern "C" -{ - /** - * @brief This function is used by FreeRTOS to configure the collection of - * time used by tasks. - * . - */ - void - vConfigureTimerForRunTimeStats (void) - { - Chip_SCT_Init (LPC_SCT1); - /* Sets match to trigger when all bits of counter are 1 */ - Chip_SCT_SetMatchCount(LPC_SCT1, SCT_MATCH_0, 0xffffffff); - /* Set corresponding match register to event */ - LPC_SCT1->EVENT[0].CTRL |= 0x1 | (0x1 << 12); - /* Enable event */ - LPC_SCT1->EVENT[0].STATE |= 0x1; - - /* Set the interrupt */ - Chip_SCT_EnableEventInt(LPC_SCT1, SCT_EVT_0); - - /* Clear timer of any pending interrupts */ - NVIC_ClearPendingIRQ(SCT0_1_IRQn); - - /* Enable timer interrupt */ - NVIC_EnableIRQ(SCT0_1_IRQn); - - /* Start timer */ - LPC_SCT1->CONFIG = SCT_CONFIG_32BIT_COUNTER; - LPC_SCT1->CTRL_U = SCT_CTRL_CLRCTR_L; - } -}