Hi,
I have an issue with reading ecap captures from /dev/counter* in Linux. Note: On the input is FAN with about 4800 rpm with 2 positive edges per revolution.
I add 4 watches:
Then I enable events, 1 > enable and can read events. However the events have a strange timing (example of 9 events):
Timestamp 0: 256226416085143 Value 0: 2161223
Timestamp 1: 256226416095528 Value 1: 2162419
Timestamp 2: 256226416098028 Value 2: 2162575
Timestamp 3: 256226416099319 Value 3: 2162731
Timestamp 4: 256226441692567 Value 4: 5361771
Timestamp 5: 256226441699117 Value 5: 5362551
Timestamp 6: 256226441700607 Value 6: 5362759
Timestamp 7: 256226441702047 Value 7: 5362915
Timestamp 8: 256226467304975 Value 8: 8563151
Timestamp 9: 256226467311111 Value 9: 8563905
Diff 0: 10385 ms
Diff 1: 2500 ms
Diff 2: 1291 ms
Diff 3: 25593248 ms
Diff 4: 6550 ms
Diff 5: 1490 ms
Diff 6: 1440 ms
Diff 7: 25602928 ms
Diff 8: 6136 ms
Standard deviation: 10640372 ms
Average difference: 5691774 ms
4 events come within a few microsecconds, so I suspect there is no contex switch happening between them.The big gap between the 4 is nearly exactly the time for 2 fan revolutions.
So I had a look at the kernel driver ti-ecap-capture.c:
This interupt sevice routine sends the events for eached latched interupt. My suspicion is that the same interrupt send all 4 events.
In the initialisation we can find this:
Where ECAP_EVT_EN_MASK translates to 0b00011000. According to the Reference manual (p1861)
Seven interrupt events (CEVT1, CEVT2, CEVT3, CEVT4, CNTOVF, TSCNT = PRD, TSCNT = CMP) can be generated. The interrupt enable register (ECAP_ECINT_EN_FLG) is used to enable/disable individual interrupt event sources. The interrupt flag register (ECAP_ECINT_EN_FLG) indicates if any interrupt event has been latched and contains the global interrupt flag ECAP_ECINT_EN_FLG[16] INT_FLG bit. An interrupt pulse is generated to the interrupt controller only if any of the interrupt events are enabled, the flag bit is 1h, and the INT_FLG flag bit is 0h. The interrupt service routine must clear the global interrupt flag bit and the serviced event via the interrupt clear register (ECAP_ECINT_CLR_FRC) before any other interrupt pulses are generated. The interrupt force register (ECAP_ECINT_CLR_FRC) can force an interrupt event. This is useful for test purposes.
this means, that an interrupt is only sent for CEVT4 (=capture3) or CNTOVF (overflow). Not for the other 3 captures.
Am I correct with this analysis? Is this a bug in the driver?
My workaround is to only activate one watch and divide the period time accordingly. This would also work when the issue is fixed. This workaround is ok for fan control but might be an issue to other applications.