joepasquariello
Well-known member
I'm pretty sure I have found and fixed a bug in FreqMeasureMultiIMXRT.cpp. Please take a look.
In FreqMeasureMulti::isr(), when the capture interrupt occurs (as opposed to the overflow interrupts), the ISR is reading register VALx for the relevant timer, and it should be reading CVALx, which is the actual capture register. VALx is always 0 on the capture interrupt, so the values returned by read() are incorrect and are always exact multiples of 65536
For example, with defaults of FREQMEASUREMULTI_RAISING and 60 Hz, the sketch output is:
60.02(2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 )
59.97(2:2490368:16.60 2:2490368:16.60 2:2555904:17.04 2:2490368:16.60 )
60.02(2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 )
59.97(2:2490368:16.60 2:2555904:17.04 2:2490368:16.60 2:2490368:16.60 )
The count values are 2490368 (0x260000) and 2555904 (0x270000). What's happening is that read() is effectively returning a 32-bit value where the upper word is the number of overflows of the 16-bit capture register, without the lower 16 bits of the actual capture value.
With the ISR changed to read CVALx rather than VALx, the output looks as shown below, with the expected 60.00 Hz
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
The VALx registers are initialized in begin(), and I'm not sure if these should also be CVALx.
pflexpwm->SM[sub_module].VAL0 = 0;
pflexpwm->SM[sub_module].VAL1 = 65535;
pflexpwm->SM[sub_module].VAL2 = 0;
pflexpwm->SM[sub_module].VAL3 = 0;
pflexpwm->SM[sub_module].VAL4 = 0;
pflexpwm->SM[sub_module].VAL5 = 0;
I've only tested the single-PWM example sketch so far, and only on default pins 5/10, but I think the same bug exists for all channels.
In FreqMeasureMulti::isr(), when the capture interrupt occurs (as opposed to the overflow interrupts), the ISR is reading register VALx for the relevant timer, and it should be reading CVALx, which is the actual capture register. VALx is always 0 on the capture interrupt, so the values returned by read() are incorrect and are always exact multiples of 65536
For example, with defaults of FREQMEASUREMULTI_RAISING and 60 Hz, the sketch output is:
60.02(2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 )
59.97(2:2490368:16.60 2:2490368:16.60 2:2555904:17.04 2:2490368:16.60 )
60.02(2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 2:2490368:16.60 )
59.97(2:2490368:16.60 2:2555904:17.04 2:2490368:16.60 2:2490368:16.60 )
The count values are 2490368 (0x260000) and 2555904 (0x270000). What's happening is that read() is effectively returning a 32-bit value where the upper word is the number of overflows of the 16-bit capture register, without the lower 16 bits of the actual capture value.
With the ISR changed to read CVALx rather than VALx, the output looks as shown below, with the expected 60.00 Hz
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
60.00(2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 2:2499968:16.67 )
The VALx registers are initialized in begin(), and I'm not sure if these should also be CVALx.
pflexpwm->SM[sub_module].VAL0 = 0;
pflexpwm->SM[sub_module].VAL1 = 65535;
pflexpwm->SM[sub_module].VAL2 = 0;
pflexpwm->SM[sub_module].VAL3 = 0;
pflexpwm->SM[sub_module].VAL4 = 0;
pflexpwm->SM[sub_module].VAL5 = 0;
I've only tested the single-PWM example sketch so far, and only on default pins 5/10, but I think the same bug exists for all channels.
Last edited: