| Electronics > Projects, Designs, and Technical Stuff |
| Measuring time span very precise |
| << < (9/16) > >> |
| HendriXML:
I'll try to summarize the things that have been said and are important: Is the counter high/low byte and flag written consistent? I assume it's atomic between 2 instructions Can the counter be read consistent? Yes by reading low byte before high byte. The high byte is kept safe. Can this reading be interrupted? Not in an interrupt, otherwise disabling interrupts is needed. Is reading the counter and the flag always consistent? No, when a overflow happened, reading the first one of them can be old news. Reading it repeatedly can assure one self of the consistency. How ever because the counter can be read consistent and there's a lot of time between overflows, one also could assume there isn't a overflow when counter is larger then x7fff. And do a check is it's less than that. This way the counter is always consistent with the flag. (Only if the counter is xffff (or a bit less) and the flag is 1, there's inconsistency) How about counting the 16+ bits? On every overflow one should be added to the high word of the 32 bit counter. Its best to take the overflow flag for that, it is like a 17th bit. But the 16 bit value can only overflow once in that bit so it has to be cleared. How to ensure the overflow isn't counted double? The code that updates the counter, should also be the one that clears the flag. This operation must not be interrupted. Within a interrupt this is ok, outside an interrupt interrupts should be disabled. How to ensure every overflow is counted? Before the counter reaches x7fff the flag should be checked, counted and cleared. The overflow interrupt is very useful for that. How to ensure that the counter and overflow flag are related? Because the captured value is old news and the overflow flag is actual, the capture interrupt must be executed before they are not related anymore. The flag is checked when the counter is less than x7fff and might be unrelated if this is done x7fff ticks after HW capturing. So interrupts should not be disabled more than a portion of that. There're different implementations possible but i think this lists what to consider. If something's missing or wrong I'd like to hear it. |
| HendriXML:
--- Quote from: Ian.M on September 08, 2019, 01:52:36 pm ---To get a consistent state for further processing you only need two identical repeated reads of the interrupt flags + the timer high bit. Initialise the old_state variable with a spare bit set and the state variable with the spare bit cleared to guarantee an initial mismatch and it simply becomes: --- Code: ---while(state!=old_state){ old_state=state; state=pack_flags_and_timer_high_bit(); //replace with inline bitwise stuff } //Smash old_state here if in main loop --- End code --- There is absolutely no need to 'blind read' or repeatedly read any capture registers, or reread the timer or keep any part of the timer value except its high bit. If you handle the various cases in the main loop, then you don't use any ISRs, and don't enable the relevant interrupts. AVR peripherals set their interrupt flag when their trigger condition is met even when that interrupt is masked or otherwise disabled, so one would simply poll the interrupt flags to grab the state as described above then handle the various cases, as if in an ISR except with worse latency (i.e. the superloop execution time). --- End quote --- As a general solution one should ensure that reading 2x an inconsistent state is not possible. (In this case that's ensured) |
| magic:
This seems correct. Writes to 16 bit counter registers are atomic if you write the high byte first and then the low byte. The high byte is remembered and applied later in the same clock cycle when the low byte is written. Interrupts must not touch the timer in the meantime. I'm not sure if this clears the overflow flag. It may need to be cleared manually; in such case you better do it fast before the timer overflows for the first time ;) --- Quote from: Ian.M on September 08, 2019, 01:52:36 pm ---To get a consistent state for further processing you only need two identical repeated reads of the interrupt flags + the timer high bit. [...] --- End quote --- That's all nice until you need to deal with an 8 bit timer running at full core clock speed :D |
| HendriXML:
The captured counter and the current overflow flag can also be unrelated. ;D That would be the case when the capture interrupt was delayed very long. I'll have to put that in the list as well. |
| Ian.M:
Consider the ATmega case with two capture units. Their timers are synchronised so there is only one overflow event, but there are two independent capture events. If the events are well spaced apart (and not too close to the timer high bit toggling) the loop only takes two passes. However if the start, stop and overflow events happen *VERY* close together, each of the later ones can invalidate the state match and force another pass of the loop. --- Quote from: magic on September 08, 2019, 02:34:59 pm ---This seems correct. Writes to 16 bit counter registers are atomic if you write the high byte first and then the low byte. The high byte is remembered and applied later in the same clock cycle when the low byte is written. Interrupts must not touch the timer in the meantime. I'm not sure if this clears the overflow flag. It may need to be cleared manually; in such case you better do it fast before the timer overflows for the first time ;) --- End quote --- Once set up you *never* need to write to the timer. You've got half the timer rollover period before the state you've grabbed becomes useless. As I edited in above, that's fractionally over 2ms on an AVR @16MHz. Use two capture units and complete the whole multi-state processing ISR including any flag clearing that needs to be done in under 2ms and you can guarantee not to miss any even if they are coincident and bang on top of a timer rollover, unless the same event recurs within your ISR execution dead time before you've read the event's capture register and cleared its flag. If you need to handle fast repeating events put grabbing any active captures from their registers immediately after the consistent state loop. You'll still be in trouble if a third event on the same channel occurs within the total ISR execution time of the second one. --- Quote from: magic on September 08, 2019, 02:34:59 pm --- --- Quote from: Ian.M on September 08, 2019, 01:52:36 pm ---To get a consistent state for further processing you only need two identical repeated reads of the interrupt flags + the timer high bit. [...] --- End quote --- That's all nice until you need to deal with an 8 bit timer running at full core clock speed :D --- End quote --- Which is why you don't try to do this sort of s--t on a 12 bit core PIC, which as they generally don't have interrupts, also dont have an interrupt flag for their 8 bit timer 0, so you have to treat it as a 7 bit timer with a (self-resetting) overflow flag in the 8th bit that worst case will only be valid for 128 instruction cycles. BTDTGTTS |O |
| Navigation |
| Message Index |
| Next page |
| Previous page |