Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
7b957116
Commit
7b957116
authored
Mar 30, 2016
by
Johny Mattsson
Browse files
Merge pull request #1203 from DiUS/reduce-tmr-time-drift
Make tmr.time() more resilient against RTC changing frequency
parents
e99f4435
858e4bf5
Changes
1
Hide whitespace changes
Inline
Side-by-side
app/modules/tmr.c
View file @
7b957116
...
@@ -68,11 +68,18 @@ typedef struct{
...
@@ -68,11 +68,18 @@ typedef struct{
}
timer_struct_t
;
}
timer_struct_t
;
typedef
timer_struct_t
*
timer_t
;
typedef
timer_struct_t
*
timer_t
;
//everybody just love unions! riiiiight?
// The previous implementation extended the rtc counter to 64 bits, and then
static
union
{
// applied rtc2sec with the current calibration value to that 64 bit value.
uint64_t
block
;
// This means that *ALL* clock ticks since bootup are counted with the *current*
uint32_t
part
[
2
];
// clock period. In extreme cases (long uptime, sudden temperature change), this
}
rtc_time
;
// could result in tmr.time() going backwards....
// This implementation instead applies rtc2usec to short time intervals only (the
// longest being around 1 second), and then accumulates the resulting microseconds
// in a 64 bit counter. That's guaranteed to be monotonic, and should be a lot closer
// to representing an actual uptime.
static
uint32_t
rtc_time_cali
=
0
;
static
uint32_t
last_rtc_time
=
0
;
static
uint64_t
last_rtc_time_us
=
0
;
static
sint32_t
soft_watchdog
=
-
1
;
static
sint32_t
soft_watchdog
=
-
1
;
static
timer_struct_t
alarm_timers
[
NUM_TMR
];
static
timer_struct_t
alarm_timers
[
NUM_TMR
];
...
@@ -248,28 +255,33 @@ static int tmr_wdclr( lua_State* L ){
...
@@ -248,28 +255,33 @@ static int tmr_wdclr( lua_State* L ){
//it tells how many rtc clock ticks represent 1us.
//it tells how many rtc clock ticks represent 1us.
//the high 64 bits of the uint64_t multiplication
//the high 64 bits of the uint64_t multiplication
//are unnedded (I did the math)
//are unnedded (I did the math)
static
uint32_t
rtc2sec
(
uint64_t
rtc
){
static
uint32_t
rtc2usec
(
uint64_t
rtc
){
uint64_t
aku
=
system_rtc_clock_cali_proc
();
return
(
rtc
*
rtc_time_cali
)
>>
12
;
aku
*=
rtc
;
return
(
aku
>>
12
)
/
1000000
;
}
}
//the following function workes, I just wrote it and didn't use it.
// This returns the number of microseconds uptime. Note that it relies on the rtc clock,
/*static uint64_t sec2rtc(uint32_t sec){
// which is notoriously temperature dependent
uint64_t aku = (1<<20)/system_rtc_clock_cali_proc();
inline
static
uint64_t
rtc_timer_update
(
bool
do_calibration
){
aku *= sec;
if
(
do_calibration
||
rtc_time_cali
==
0
)
return (aku>>8)*1000000;
rtc_time_cali
=
system_rtc_clock_cali_proc
();
}*/
inline
static
void
rtc_timer_update
(){
uint32_t
current
=
system_get_rtc_time
();
uint32_t
current
=
system_get_rtc_time
();
if
(
rtc_time
.
part
[
0
]
>
current
)
//overflow check
uint32_t
since_last
=
current
-
last_rtc_time
;
// This will transparently deal with wraparound
rtc_time
.
part
[
1
]
++
;
uint32_t
us_since_last
=
rtc2usec
(
since_last
);
rtc_time
.
part
[
0
]
=
current
;
uint64_t
now
=
last_rtc_time_us
+
us_since_last
;
// Only update if at least 100ms has passed since we last updated.
// This prevents the rounding errors in rtc2usec from accumulating
if
(
us_since_last
>=
100000
)
{
last_rtc_time
=
current
;
last_rtc_time_us
=
now
;
}
return
now
;
}
}
void
rtc_callback
(
void
*
arg
){
void
rtc_callback
(
void
*
arg
){
rtc_timer_update
();
rtc_timer_update
(
true
);
if
(
soft_watchdog
>
0
){
if
(
soft_watchdog
>
0
){
soft_watchdog
--
;
soft_watchdog
--
;
if
(
soft_watchdog
==
0
)
if
(
soft_watchdog
==
0
)
...
@@ -279,8 +291,8 @@ void rtc_callback(void *arg){
...
@@ -279,8 +291,8 @@ void rtc_callback(void *arg){
// Lua: tmr.time() , return rtc time in second
// Lua: tmr.time() , return rtc time in second
static
int
tmr_time
(
lua_State
*
L
){
static
int
tmr_time
(
lua_State
*
L
){
rtc_timer_update
();
uint64_t
us
=
rtc_timer_update
(
false
);
lua_pushinteger
(
L
,
rtc2sec
(
rtc_time
.
block
)
);
lua_pushinteger
(
L
,
us
/
1000000
);
return
1
;
return
1
;
}
}
...
@@ -318,7 +330,9 @@ int luaopen_tmr( lua_State *L ){
...
@@ -318,7 +330,9 @@ int luaopen_tmr( lua_State *L ){
alarm_timers
[
i
].
mode
=
TIMER_MODE_OFF
;
alarm_timers
[
i
].
mode
=
TIMER_MODE_OFF
;
ets_timer_disarm
(
&
alarm_timers
[
i
].
os
);
ets_timer_disarm
(
&
alarm_timers
[
i
].
os
);
}
}
rtc_time
.
block
=
0
;
last_rtc_time
=
system_get_rtc_time
();
// Right now is time 0
last_rtc_time_us
=
0
;
ets_timer_disarm
(
&
rtc_timer
);
ets_timer_disarm
(
&
rtc_timer
);
ets_timer_setfn
(
&
rtc_timer
,
rtc_callback
,
NULL
);
ets_timer_setfn
(
&
rtc_timer
,
rtc_callback
,
NULL
);
ets_timer_arm_new
(
&
rtc_timer
,
1000
,
1
,
1
);
ets_timer_arm_new
(
&
rtc_timer
,
1000
,
1
,
1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment