SENT: count HW timer overcapture events

Currently only count.
TODO: handle
This commit is contained in:
Andrey Gusakov 2024-12-07 00:35:11 +03:00 committed by rusefillc
parent ceefab2eed
commit f267011daf
4 changed files with 46 additions and 10 deletions

View File

@ -291,9 +291,18 @@ int sent_channel::FastChannelDecoder(uint32_t clocks) {
return 0;
}
int sent_channel::Decoder(uint32_t clocks) {
int sent_channel::Decoder(uint32_t clocks, uint8_t flags) {
int ret;
#if SENT_STATISTIC_COUNTERS
if (flags & SENT_FLAG_HW_OVERFLOW) {
statistic.hwOverflowCnt++;
}
#endif
/* TODO: handle flags */
(void)flags;
ret = FastChannelDecoder(clocks);
if (ret > 0) {
/* valid packet received, can process slow channels */
@ -569,6 +578,8 @@ void sent_channel::Info() {
}
#if SENT_STATISTIC_COUNTERS
efiPrintf("HW overflows %lu\n", statistic.hwOverflowCnt);
efiPrintf("Pause pulses %lu\n", statistic.PauseCnt);
efiPrintf("Restarts %lu", statistic.RestartCnt);
efiPrintf("Interval errors %lu short, %lu long", statistic.ShortIntervalErr, statistic.LongIntervalErr);
@ -590,9 +601,9 @@ static MAILBOX_DECL(sent_mb, sent_mb_buffer, SENT_MB_SIZE);
static THD_WORKING_AREA(waSentDecoderThread, 256);
void SENT_ISR_Handler(uint8_t channel, uint16_t clocks) {
void SENT_ISR_Handler(uint8_t channel, uint16_t clocks, uint8_t flags) {
/* encode to fit msg_t */
msg_t msg = (channel << 16) | clocks;
msg_t msg = (flags << 24) | (channel << 16) | clocks;
/* called from ISR */
chSysLockFromISR();
@ -610,11 +621,12 @@ static void SentDecoderThread(void*) {
if (ret == MSG_OK) {
uint16_t tick = msg & 0xffff;
uint8_t n = (msg >> 16) & 0xff;
uint8_t flags = (msg >> 24) & 0xff;
if (n < SENT_CHANNELS_NUM) {
sent_channel &channel = channels[n];
if (channel.Decoder(tick) > 0) {
if (channel.Decoder(tick, flags) > 0) {
/* report only for first channel */
if (n == 0) {
uint16_t sig0, sig1;

View File

@ -14,8 +14,10 @@
/* SENT decoder init */
void initSent();
#define SENT_FLAG_HW_OVERFLOW (1 << 0)
/* ISR hook */
void SENT_ISR_Handler(uint8_t ch, uint16_t val_res);
void SENT_ISR_Handler(uint8_t channels, uint16_t clocks, uint8_t flags);
/* Stop/Start for config update */
void startSent();

View File

@ -22,32 +22,46 @@
/* This SENT HW driver is based on ChibiOS ICU driver */
#if (HAL_USE_ICU == TRUE)
/* TODO: do we care about scaling abstract timer ticks to some time base? */
/* TODO: get at runtime */
/* Max timer clock for most timers on STM32 is CPU clock / 2 */
#define SENT_TIMER_CLOCK_DIV 2
#define SENT_ICU_FREQ (CORE_CLOCK / SENT_TIMER_CLOCK_DIV) // == CPU freq / 2
static uint16_t lastPulse[SENT_INPUT_COUNT];
static bool overcapture[SENT_INPUT_COUNT];
static void icuperiodcb(ICUDriver *icup, size_t index)
{
uint16_t clocks;
uint8_t flags = 0;
const ICUConfig *icucfg = icup->config;
if ((icucfg->channel == ICU_CHANNEL_1) || (icucfg->channel == ICU_CHANNEL_2)) {
/* channel 1 and channel 2 supports period measurements */
SENT_ISR_Handler(index, icuGetPeriodX(icup) * SENT_TIMER_CLOCK_DIV);
clocks = icuGetPeriodX(icup);
} else {
/* this is freerunnig timer and we need to calculate period using just captured timer value and previous one */
/* TODO: support 32 bit timers too? */
uint16_t val = icuGetWidthX(icup);
/* can overflow */
uint16_t clocks = val - lastPulse[index];
SENT_ISR_Handler(index, clocks /* * SENT_TIMER_CLOCK_DIV */);
clocks = val - lastPulse[index];
lastPulse[index] = val;
}
if (overcapture[index]) {
flags |= SENT_FLAG_HW_OVERFLOW;
overcapture[index] = false;
}
SENT_ISR_Handler(index, clocks, flags);
}
static void icuovercapture(ICUDriver *icup, size_t index)
{
overcapture[index] = true;
}
/* ICU callbacks */
@ -56,6 +70,11 @@ static void icuperiodcb_in1(ICUDriver *icup)
icuperiodcb(icup, 0);
}
static void icuovercapture_in1(ICUDriver *icup)
{
icuovercapture(icup, 0);
}
/* ICU configs */
static ICUConfig icucfg[SENT_INPUT_COUNT] =
{
@ -68,6 +87,7 @@ static ICUConfig icucfg[SENT_INPUT_COUNT] =
.channel = ICU_CHANNEL_1, /* will be overwriten on startSent() */
.dier = 0U,
.arr = 0xFFFFFFFFU,
.overcapture_cb = icuovercapture_in1,
}
};

View File

@ -30,6 +30,8 @@ typedef enum
} SENT_STATE_enum;
struct sent_channel_stat {
uint32_t hwOverflowCnt;
uint32_t ShortIntervalErr;
uint32_t LongIntervalErr;
uint32_t SyncErr;
@ -107,7 +109,7 @@ public:
#endif // SENT_STATISTIC_COUNTERS
/* Decoder */
int Decoder(uint32_t clocks);
int Decoder(uint32_t clocks, uint8_t flags = 0);
/* Get last raw message */
int GetMsg(uint32_t* rx);