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
858e4bf5
Commit
858e4bf5
authored
Mar 24, 2016
by
Bernd Meyer
Committed by
Johny Mattsson
Mar 30, 2016
Browse files
Make tmr.time() more resilient against RTC changing frequency
parent
41037ef3
Changes
1
Hide whitespace changes
Inline
Side-by-side
app/modules/tmr.c
View file @
858e4bf5
...
...
@@ -68,11 +68,18 @@ typedef struct{
}
timer_struct_t
;
typedef
timer_struct_t
*
timer_t
;
//everybody just love unions! riiiiight?
static
union
{
uint64_t
block
;
uint32_t
part
[
2
];
}
rtc_time
;
// The previous implementation extended the rtc counter to 64 bits, and then
// applied rtc2sec with the current calibration value to that 64 bit value.
// This means that *ALL* clock ticks since bootup are counted with the *current*
// clock period. In extreme cases (long uptime, sudden temperature change), this
// 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
timer_struct_t
alarm_timers
[
NUM_TMR
];
...
...
@@ -248,28 +255,33 @@ static int tmr_wdclr( lua_State* L ){
//it tells how many rtc clock ticks represent 1us.
//the high 64 bits of the uint64_t multiplication
//are unnedded (I did the math)
static
uint32_t
rtc2sec
(
uint64_t
rtc
){
uint64_t
aku
=
system_rtc_clock_cali_proc
();
aku
*=
rtc
;
return
(
aku
>>
12
)
/
1000000
;
static
uint32_t
rtc2usec
(
uint64_t
rtc
){
return
(
rtc
*
rtc_time_cali
)
>>
12
;
}
//the following function workes, I just wrote it and didn't use it.
/*static uint64_t sec2rtc(uint32_t sec){
uint64_t aku = (1<<20)/system_rtc_clock_cali_proc();
aku *= sec;
return (aku>>8)*1000000;
}*/
// This returns the number of microseconds uptime. Note that it relies on the rtc clock,
// which is notoriously temperature dependent
inline
static
uint64_t
rtc_timer_update
(
bool
do_calibration
){
if
(
do_calibration
||
rtc_time_cali
==
0
)
rtc_time_cali
=
system_rtc_clock_cali_proc
();
inline
static
void
rtc_timer_update
(){
uint32_t
current
=
system_get_rtc_time
();
if
(
rtc_time
.
part
[
0
]
>
current
)
//overflow check
rtc_time
.
part
[
1
]
++
;
rtc_time
.
part
[
0
]
=
current
;
uint32_t
since_last
=
current
-
last_rtc_time
;
// This will transparently deal with wraparound
uint32_t
us_since_last
=
rtc2usec
(
since_last
);
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
){
rtc_timer_update
();
rtc_timer_update
(
true
);
if
(
soft_watchdog
>
0
){
soft_watchdog
--
;
if
(
soft_watchdog
==
0
)
...
...
@@ -279,8 +291,8 @@ void rtc_callback(void *arg){
// Lua: tmr.time() , return rtc time in second
static
int
tmr_time
(
lua_State
*
L
){
rtc_timer_update
();
lua_pushinteger
(
L
,
rtc2sec
(
rtc_time
.
block
)
);
uint64_t
us
=
rtc_timer_update
(
false
);
lua_pushinteger
(
L
,
us
/
1000000
);
return
1
;
}
...
...
@@ -318,7 +330,9 @@ int luaopen_tmr( lua_State *L ){
alarm_timers
[
i
].
mode
=
TIMER_MODE_OFF
;
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_setfn
(
&
rtc_timer
,
rtc_callback
,
NULL
);
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