threadx icon indicating copy to clipboard operation
threadx copied to clipboard

Define system clock as ULONG64

Open joelguittet opened this issue 1 year ago • 6 comments

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.

joelguittet avatar Aug 08 '24 21:08 joelguittet

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.

fdesbiens avatar Feb 27 '25 14:02 fdesbiens

@eclipse-threadx/iot-threadx-committers and @eclipse-threadx/iot-threadx-contributors: Please provide your feedback.

fdesbiens avatar Mar 19 '25 18:03 fdesbiens

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 avatar Mar 19 '25 18:03 billlamiework

@billlamiework sounds a good option to me. If I make a PR, would it be reviewed ?

joelguittet avatar Mar 20 '25 06:03 joelguittet

@joelguittet Yes, please submit a PR.

fdesbiens avatar Apr 01 '25 16:04 fdesbiens

very good idea, long awaited feature

tdjastrzebski avatar Aug 10 '25 11:08 tdjastrzebski

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)

pkusbel avatar Jan 02 '26 22:01 pkusbel