auto-sync
This commit is contained in:
parent
6b84da1f57
commit
aeac9d6732
|
@ -159,7 +159,7 @@ uint64_t getTimeNowUs(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getTimeNowNt(void) {
|
uint64_t getTimeNowNt(void) {
|
||||||
return halTime.get(hal_lld_get_counter_value(), false);
|
return halTime.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//uint64_t getHalTimer(void) {
|
//uint64_t getHalTimer(void) {
|
||||||
|
@ -218,7 +218,11 @@ static void onEvenyGeneralMilliseconds(Engine *engine) {
|
||||||
/**
|
/**
|
||||||
* We need to push current value into the 64 bit counter often enough so that we do not miss an overflow
|
* We need to push current value into the 64 bit counter often enough so that we do not miss an overflow
|
||||||
*/
|
*/
|
||||||
halTime.get(hal_lld_get_counter_value(), true);
|
bool alreadyLocked = lockAnyContext();
|
||||||
|
updateAndSet(&halTime.state, hal_lld_get_counter_value());
|
||||||
|
if (!alreadyLocked) {
|
||||||
|
unlockAnyContext();
|
||||||
|
}
|
||||||
|
|
||||||
if (!engine->rpmCalculator.isRunning())
|
if (!engine->rpmCalculator.isRunning())
|
||||||
writeToFlashIfPending();
|
writeToFlashIfPending();
|
||||||
|
@ -390,7 +394,6 @@ void initEngineContoller(Engine *engine) {
|
||||||
*/
|
*/
|
||||||
prepareShapes(engine);
|
prepareShapes(engine);
|
||||||
|
|
||||||
|
|
||||||
initMalfunctionCentral();
|
initMalfunctionCentral();
|
||||||
|
|
||||||
#if EFI_ELECTRONIC_THROTTLE_BODY
|
#if EFI_ELECTRONIC_THROTTLE_BODY
|
||||||
|
|
|
@ -232,7 +232,7 @@ static void triggerInfo(Engine *engine) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EFI_PROD_CODE
|
#if EFI_PROD_CODE
|
||||||
scheduleMsg(&logger, "maxLockTime=%d", maxLockTime);
|
scheduleMsg(&logger, "maxLockTime=%d / maxTriggerReentraint=%d", maxLockTime, maxTriggerReentraint);
|
||||||
scheduleMsg(&logger, "primary trigger simulator: %s %s freq=%d",
|
scheduleMsg(&logger, "primary trigger simulator: %s %s freq=%d",
|
||||||
hwPortname(boardConfiguration->triggerSimulatorPins[0]),
|
hwPortname(boardConfiguration->triggerSimulatorPins[0]),
|
||||||
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]),
|
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]),
|
||||||
|
|
|
@ -252,7 +252,7 @@ static int rtcStartTime;
|
||||||
|
|
||||||
static void timeInfo(void) {
|
static void timeInfo(void) {
|
||||||
scheduleMsg(&logger, "chTimeNow as seconds = %d", getTimeNowSeconds());
|
scheduleMsg(&logger, "chTimeNow as seconds = %d", getTimeNowSeconds());
|
||||||
scheduleMsg(&logger, "hal seconds = %d", halTime.get(hal_lld_get_counter_value(), false) / 168000000LL);
|
scheduleMsg(&logger, "hal seconds = %d", halTime.get() / 168000000LL);
|
||||||
|
|
||||||
#if EFI_RTC
|
#if EFI_RTC
|
||||||
int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime;
|
int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime;
|
||||||
|
|
|
@ -5,8 +5,16 @@
|
||||||
* @author Andrey Belomutskiy, (c) 2012-2014
|
* @author Andrey Belomutskiy, (c) 2012-2014
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#if (EFI_PROD_CODE || EFI_SIMULATOR)
|
||||||
|
#define GET_VALUE() hal_lld_get_counter_value()
|
||||||
|
#else
|
||||||
|
#define GET_VALUE() 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "efilib2.h"
|
#include "efilib2.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main use-case of this class is to keep track of a 64-bit global number of CPU ticks from reset.
|
* The main use-case of this class is to keep track of a 64-bit global number of CPU ticks from reset.
|
||||||
*
|
*
|
||||||
|
@ -18,24 +26,54 @@
|
||||||
* In order for this to function, it's your responsibility to invoke offer() method at least once a second.
|
* In order for this to function, it's your responsibility to invoke offer() method at least once a second.
|
||||||
*/
|
*/
|
||||||
Overflow64Counter::Overflow64Counter() {
|
Overflow64Counter::Overflow64Counter() {
|
||||||
currentBase = 0;
|
state.highBits = 0;
|
||||||
currentValue = 0;
|
state.lowBits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Overflow64Counter::get(uint32_t value, int isPrimaryThread) {
|
/**
|
||||||
// this method is lock-free, only one thread is allowed to commit state
|
* in order to have atomic writes this should be invoked within a critical section
|
||||||
|
*/
|
||||||
|
void updateAndSet(State64 *state, uint32_t value) {
|
||||||
|
if (value < state->lowBits) {
|
||||||
|
// new value less than previous value means there was an overflow in that 32 bit counter
|
||||||
|
state->highBits += 0x100000000LL;
|
||||||
|
}
|
||||||
|
state->lowBits = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Overflow64Counter::update(uint32_t value) {
|
||||||
|
updateAndSet(&state, value);
|
||||||
|
return state.highBits + state.lowBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: make this a macro? always inline?
|
||||||
|
uint64_t Overflow64Counter::get() {
|
||||||
|
/**
|
||||||
|
* this method is lock-free and thread-safe, that's because the 'update' method
|
||||||
|
* is atomic with a critical zone requirement.
|
||||||
|
*
|
||||||
|
* http://stackoverflow.com/questions/5162673/how-to-read-two-32bit-counters-as-a-64bit-integer-without-race-condition
|
||||||
|
*/
|
||||||
// these are local copies for thread-safery
|
// these are local copies for thread-safery
|
||||||
// todo: this is still not atomic, so technically not thread safe.
|
// todo: this is still not atomic, so technically not thread safe.
|
||||||
uint32_t localValue = currentValue;
|
uint64_t localH;
|
||||||
uint64_t localBase = currentBase;
|
uint32_t localLow;
|
||||||
if (value < localValue) {
|
while (true) {
|
||||||
// new value less than previous value means there was an overflow in that 32 bit counter
|
localH = state.highBits;
|
||||||
localBase += 0x100000000LL;
|
localLow = state.lowBits;
|
||||||
|
uint64_t localH2 = state.highBits;
|
||||||
|
if (localH == localH2)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (isPrimaryThread) {
|
/**
|
||||||
currentValue = value;
|
* We need to take current counter after making a local 64 bit snapshot
|
||||||
currentBase = localBase;
|
*/
|
||||||
|
uint32_t value = GET_VALUE();
|
||||||
|
|
||||||
|
if (value < localLow) {
|
||||||
|
// new value less than previous value means there was an overflow in that 32 bit counter
|
||||||
|
localH += 0x100000000LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return localBase + value;
|
return localH + value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,22 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t highBits;
|
||||||
|
uint32_t lowBits;
|
||||||
|
} State64;
|
||||||
|
|
||||||
|
void updateAndSet(State64 *state, uint32_t value);
|
||||||
|
|
||||||
class Overflow64Counter
|
class Overflow64Counter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Overflow64Counter();
|
Overflow64Counter();
|
||||||
|
|
||||||
uint64_t get(uint32_t value, int isPrimaryThread);
|
uint64_t get();
|
||||||
|
uint64_t update(uint32_t value);
|
||||||
|
|
||||||
private:
|
State64 state;
|
||||||
uint64_t currentBase;
|
|
||||||
uint32_t currentValue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* EFILIB2_H_ */
|
#endif /* EFILIB2_H_ */
|
||||||
|
|
|
@ -41,13 +41,13 @@ void testOverflow64Counter(void) {
|
||||||
print("*************************************** testOverflow64Counter\r\n");
|
print("*************************************** testOverflow64Counter\r\n");
|
||||||
|
|
||||||
Overflow64Counter o;
|
Overflow64Counter o;
|
||||||
assertEquals(0, o.get(0, true));
|
assertEquals(0, o.update(0));
|
||||||
assertEquals(10, o.get(10, true));
|
assertEquals(10, o.update(10));
|
||||||
|
|
||||||
assertEquals(20, o.get(20, true));
|
assertEquals(20, o.update(20));
|
||||||
|
|
||||||
// overflow
|
// overflow
|
||||||
assertEquals(4294967296, o.get(0, true));
|
assertEquals(4294967296, o.update(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCyclicBuffer(void) {
|
void testCyclicBuffer(void) {
|
||||||
|
|
Loading…
Reference in New Issue