Define system clock as ULONG64
Is your feature request related to a problem? Please describe.
Currently the system clock _tx_timer_system_clock is defined as an ULONG variable, so it's 32-bits unsigned, maximum value is 4294967295. With standard configuration using a 10ms timer tick, this means the timer will overlap avec 497 days only.
While it's maybe not a problem, it can be very nice to set the system time with the current epoch time.
That means currently taking the epoch time and multiply by TX_TIMER_TICKS_PER_SECOND to call tx_time_set function
Problem is actually with such resolution this overlap the ULONG internal system time.
Example: Thursday 8 August 2024 20:00:00 GMT is 1723147200 so multiply by 100 this means 172314720000 which is larger than 4294967295.
Describe the solution you'd like
I would like the internal system clock _tx_timer_system_clock to be defined as an ULONG64 so that there is no overlap at all to consider and we can set the wanted system time with the wanted timer tick resolution. tx_timer_set should take an ULONG64 type. tx_timer_get should returns an ULONG64 type as well.
I can propose a Pull Request if this is appreciated. In my opinion we can safely change the type of the system time as it will be larger than the existing type. Existing applications will just have implicit casts in case they still use an ULONG variable.
Describe alternatives you've considered Maintaining myself the system time outside of ThreadX. Not very convenient.
Additional context My application has an SNTP client that periodically check for NTP time. It would be great to set have such feature so that the SNTP client just update the ThreadX system time and then other modules of the application just call the ThreadX API to get system time.
My apologies for the delayed feedback, @joelguittet.
I will flag this issue for discussion with the committer team. I should be able to get back to you in the upcoming weeks.
@eclipse-threadx/iot-threadx-committers and @eclipse-threadx/iot-threadx-contributors: Please provide your feedback.
Unfortunately, this API and functionality change could impact existing customers. The only option would be to make this configurable under conditional compilation, where the current behavior is the default.
@billlamiework sounds a good option to me. If I make a PR, would it be reviewed ?
@joelguittet Yes, please submit a PR.
very good idea, long awaited feature
Got annoyed by this recently where I have a requirement for a 1ms tick, and now the wraparound happens too fast. I also had a need to not add a lot of overhead to the timers by changing everything to 64 bits, I needed to keep the timer expiration lightweight with minimal overhead. Rather than making everything 64 bits with the added complexity and overhead, I took a different approach: I kept everything the same and just tracked timer overflow separately.
I created a simple little patch below for anyone that wants it that adds 64 bit support while maintaining backwards compatibility. I added a tx_time_get_ext() API that returns a 64 bit value, added another 32 bit counter to track the upper 32 bits, and tied it all together in the tick interrupt handler. I only did this for the Cortex M33 port (that's what I'm using now), but the logic for other 32 bit ARM ports will be the same.
This patch does not affect how the timers run or how they expire and is fully backwards compatible with previous versions. The timers and their expiration is still 32 bits, this effectively just keeps track of time with 64 bit resolution which is what the OP wanted and what I needed, but has no impact on any other part of the system. So no overhead to existing functionality, no overhead of 64 bit math in the timer processing / expiration, and no special handling for timer expiration. The only overhead is an extra 32 bit value for the extended time and a couple extra assembly instructions in the tick ISR to update the extended time when the main timer is updated.
copy this into a patch, and run
git patch apply
to use:
call tx_time_get_ext() to get the 64 bit time call tx_time_set_ext() to set the time to a 64 bit value
I can create a PR if the team thinks this is useful
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 715e64c7..7b1d1501 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -110,7 +110,9 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_timeout.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_wait_abort.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_time_get.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_get_ext.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_time_set.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_time_set_ext.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_activate.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_change.c
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_create.c
diff --git a/common/inc/tx_api.h b/common/inc/tx_api.h
index 629d1ab9..1c43568f 100644
--- a/common/inc/tx_api.h
+++ b/common/inc/tx_api.h
@@ -1218,7 +1218,9 @@ UINT _tx_trace_interrupt_control(UINT new_posture);
#define tx_thread_wait_abort _tx_thread_wait_abort
#define tx_time_get _tx_time_get
+#define tx_time_get_ext _tx_time_get_ext
#define tx_time_set _tx_time_set
+#define tx_time_set_ext _tx_time_set_ext
#define tx_timer_activate _tx_timer_activate
#define tx_timer_change _tx_timer_change
#define tx_timer_create _tx_timer_create
@@ -1341,7 +1343,9 @@ UINT _tx_trace_interrupt_control(UINT new_posture);
#define tx_thread_wait_abort _txr_thread_wait_abort
#define tx_time_get _tx_time_get
+#define tx_time_get_ext _tx_time_get_ext
#define tx_time_set _tx_time_set
+#define tx_time_set_ext _tx_time_set_ext
#define tx_timer_activate _txr_timer_activate
#define tx_timer_change _txr_timer_change
#define tx_timer_create(t,n,e,i,c,r,a) _txr_timer_create((t),(n),(e),(i),(c),(r),(a),(sizeof(TX_TIMER)))
@@ -1452,7 +1456,9 @@ UINT _tx_el_interrupt_control(UINT new_posture);
#define tx_thread_wait_abort _txe_thread_wait_abort
#define tx_time_get _tx_time_get
+#define tx_time_get_ext _tx_time_get_ext
#define tx_time_set _tx_time_set
+#define tx_time_set_ext _tx_time_set_ext
#define tx_timer_activate _txe_timer_activate
#define tx_timer_change _txe_timer_change
#define tx_timer_create(t,n,e,i,c,r,a) _txe_timer_create((t),(n),(e),(i),(c),(r),(a),(sizeof(TX_TIMER)))
@@ -1856,7 +1862,9 @@ UINT _tx_timer_performance_system_info_get(ULONG *activates, ULONG *react
ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts);
ULONG _tx_time_get(VOID);
+ULONG64 _tx_time_get_ext(VOID);
VOID _tx_time_set(ULONG new_time);
+VOID _tx_time_set_ext(ULONG64 new_time);
/* Define error checking shells for API services. These are only referenced by the
diff --git a/common/inc/tx_timer.h b/common/inc/tx_timer.h
index 4703b14d..7cca706e 100644
--- a/common/inc/tx_timer.h
+++ b/common/inc/tx_timer.h
@@ -83,6 +83,9 @@ VOID _tx_timer_thread_entry(ULONG timer_thread_input);
TIMER_DECLARE volatile ULONG _tx_timer_system_clock;
+/* Define upper 32 bit wraparound count, which extends time to 64 bits
+*/
+TIMER_DECLARE volatile ULONG _tx_timer_system_clock_extended;
/* Define the current time slice value. If non-zero, a time-slice is active.
Otherwise, the time_slice is not active. */
diff --git a/common/src/tx_time_get_ext.c b/common/src/tx_time_get_ext.c
new file mode 100644
index 00000000..5ae7bbfd
--- /dev/null
+++ b/common/src/tx_time_get_ext.c
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * Copyright (c) 2025 Bitflip Engineering
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * SPDX-License-Identifier: MIT
+ **************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+ULONG64 _tx_time_get_ext(VOID)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+ /* create the 64 bit time by OR'd in the upper and lower 32 bits */
+ temp_time = ((ULONG64)_tx_timer_system_clock_extended << 32) | _tx_timer_system_clock;
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ /* Return the time. */
+ return(temp_time);
+}
+
+
+
+
diff --git a/common/src/tx_time_set_ext.c b/common/src/tx_time_set_ext.c
new file mode 100644
index 00000000..877ad2c0
--- /dev/null
+++ b/common/src/tx_time_set_ext.c
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright (c) 2025 Bitflip Engineering
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * SPDX-License-Identifier: MIT
+ **************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_timer.h"
+
+
+VOID _tx_time_set_ext(ULONG64 new_time)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+
+ /* Disable interrupts. */
+ TX_DISABLE
+
+
+ /* Set the system clock time. */
+ _tx_timer_system_clock = (ULONG)new_time;
+ _tx_timer_system_clock_extended = (ULONG)(new_time >> 32);
+
+ /* Restore interrupts. */
+ TX_RESTORE
+}
+
diff --git a/common/src/tx_timer_initialize.c b/common/src/tx_timer_initialize.c
index 1ae442df..2ad40f4f 100644
--- a/common/src/tx_timer_initialize.c
+++ b/common/src/tx_timer_initialize.c
@@ -39,6 +39,7 @@
periodic timer interrupt processing. */
volatile ULONG _tx_timer_system_clock;
+volatile ULONG _tx_timer_system_clock_extended;
/* Define the time-slice expiration flag. This is used to indicate that a time-slice
diff --git a/ports/cortex_m33/gnu/src/tx_timer_interrupt.S b/ports/cortex_m33/gnu/src/tx_timer_interrupt.S
index 2e215343..f7b6c6d1 100644
--- a/ports/cortex_m33/gnu/src/tx_timer_interrupt.S
+++ b/ports/cortex_m33/gnu/src/tx_timer_interrupt.S
@@ -84,9 +84,13 @@ _tx_timer_interrupt:
// _tx_timer_system_clock++;
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r2, =_tx_timer_system_clock_extended // upper 32 bits
LDR r0, [r1, #0] // Pickup system clock
- ADD r0, r0, #1 // Increment system clock
+ LDR r3, [r2] // load upper 32 bits
+ ADDS r0, r0, #1 // Increment system clock
+ ADC r3, r3, #0 // add carry to upper 32 if carry occurs
STR r0, [r1, #0] // Store new system clock
+ STR r3, [r2] // Store upper 32 extended bits
/* Test for time-slice expiration. */
// if (_tx_timer_time_slice)