#avr Logs

Dec 05 2021

#avr Calendar

10:25 AM josuah: I am facing some nice challenge with measuring time!
10:33 AM josuah: 8 bits MCUs overflow very fast! there is a couple of 16bit timer register on my chip but still...
10:33 AM josuah: so no way around: I'll have to use a global counter and the handy "timer overflow interrupt" TOIE0 that increments it
10:33 AM josuah: but then the time is spread on *two* places: one on a global variable (memory), easy to avoid race conditions on that with sei()/cli() during read/write
10:33 AM josuah: but nothing for the timer's own register!
10:33 AM josuah: so here is what I will try (crazy?):
10:33 AM josuah: read the memory variable with sei()/cli(), I am sure of reading an uint64_t atomically, that's ok
10:37 AM josuah: for that, I think I can read the interrupt flag
10:37 AM josuah: let's see... :)
10:38 AM josuah: if you hear someone screaming "I DID IT" down street, that might have been me.
11:01 AM exp: i'm no expert in this, but i don't really understand this problem
11:01 AM exp: ISRs run effectively immediately
11:01 AM exp: so how to ensure there's no overflow? make sure your ISR is short
11:02 AM exp: incrementing a variable in memory doesn't take long, nor does copying it out, and interrupts are already disabled in ISRs
11:02 AM josuah: yes, but what if an overflow happen during this short ISR time?
11:02 AM exp: how could it, you've a set number of cycles between overflows
11:02 AM josuah: yes I'm mistaken on that last sentense
11:03 AM exp: ultimately, the principle which governs your thoughts is the nyquist frequency
11:03 AM josuah: I am interested at the moment I measure time
11:03 AM exp: you must sample frequently enough to catch the overflows
11:03 AM exp: but it is a mistaken approach i think
11:04 AM exp: when you want to sample, you copy the current timer value and the overflow counter to a separate area of memory, as long as that operation and the ISR (plus entry + exit etc) is shorter than your minimum overflow time you're still good
11:04 AM exp: can you give more fixed numbers? what do you expect to detect and with what precision and accuracy?
11:05 AM josuah: I will show a code example
11:05 AM exp: also part number and clock setup is useful for people passively reading too
11:06 AM josuah: not shorter than the minimal overflow time: "timer_gettime()" might happen at any moment no? called from main application code, not from interrupt
11:09 AM exp: i'd have to go check the code, but i doubt it's very long running function?
11:10 AM exp: and yes an overflow might happen during it, but it will atomically retrieve the value, the overflow flag will be set and the ISR called once the interrupt resumes
11:10 AM exp: so as long as no overflow can happen again within that time, you'll catch them all
11:11 AM qu1j0t3: gotta
11:12 AM josuah: https://josuah.net/p/timer-overflow-and-reading-time.c
11:13 AM josuah: qu1j0t3: :D
11:14 AM exp: ok josuah i think that does explain it quite well, you're concerned that running cli() will stop the registration of an overflow but won't stop the timer actually overflowing before you sample the value
11:15 AM josuah: yes! why did I not explain it like you just did from the start, it would have been much easier then.
11:15 AM exp: does that sound correct?
11:15 AM josuah: hehe, me and language
11:15 AM exp: the easiest option here is also the least 'pure'
11:16 AM exp: cli is a trivial operation, i think it's one register write
11:16 AM exp: you know the frequency your counter is running at
11:16 AM josuah: compute how many instructions ago it was?
11:16 AM exp: thus, you know the possible output values that do indicate an overflow
11:16 AM josuah: ah, yeah :) thought about it as well
11:16 AM exp: i don't know what build system you are using, but there are usually macros accessible for this
11:16 AM exp: F_CPU and the like
11:17 AM exp: so you do not need to hardcode it, as long as you have defined your counter frequencies similarly
11:17 AM josuah: atmega328p, with F_CPU from avr-libc yes
11:17 AM exp: you should also statically assert they are reasonable values
11:17 AM exp: (ie that you don't somehow get an overflow margin > maximum counter value)
11:17 AM josuah: it could be some gettime.S per-arch or the like
11:18 AM exp: as i say i'm no expert on this, i'm a decided amateur, but the problem you describe i think does exist
11:18 AM exp: i don't know of any mechanism which would prevent the overflow at that particular cycle
11:18 AM josuah: a race condition with an actual clock! :D
11:19 AM josuah: the clock always win
11:19 AM exp: from a functional point of view however, the mechanism of a slight execution delay is just the rotation of the counter 'field' slightly
11:19 AM josuah: thank you for going through the trouble of understanding my somehow cryptic explanations
11:19 AM exp: if your max value is 100, your execution delay is always 1 cycle, then 01 is 00, and 100 is 99
11:20 AM josuah: maybe that is why CPU cycles of each instruction is given by the datasheet
11:20 AM exp: there are asynchronous parts of AVRs, so if you plan to use this across sleep modes you'll need a lot more care
11:21 AM exp: but other than that there's generally a single clock source that gets distributed and divided or multiplied
11:21 AM exp: (there are some auxillary things like 32khz oscillators and the like, internal and external)
11:23 AM exp: with regard to your C code above, i would not add the branch there, i would always use the sample post cli and just apply the logic as discussed to whether the overflow counter should be incremented by 1
11:24 AM exp: the 'rule' for how long the atomic block (if you're using the gnu toolchain, use that macro too) should be is what i originally thought you were asking
11:24 AM exp: but it can be as short as copying the two values out, the conditional does not need to run atomically
11:26 AM exp: in fact thinking about it don't even bother with the overflow counter, just decrement by the number of cycles you can statically calculate, easier on everyone and zero branching required
11:26 AM exp: apologies for the rambling thoughts, it's a sunday afternoon :-)
11:26 AM josuah: no quite the opposite, I enjoy reading this!
11:27 AM josuah: which branch would you advise avoiding? (t0 > t1) or (*TIMSK0 | TOIE0)?
11:27 AM josuah: I will try counting the cycles
11:28 AM exp: the former, but i think the smartest plan is actually probably just to do the straight up multiplication in the ISR, because that's the shortest possible code segment and the least confusing
11:28 AM josuah: yes ok, catching up
11:28 AM exp: assuming you're getting an int64 out which is overflow*max+val
11:29 AM josuah: not a bad idea! then I can have busy wait-loops more reactive!
11:29 AM josuah: josuah is learning to be on time tonight!
11:29 AM exp: there are.. minor concerns
11:30 AM exp: ISR entries are not free, so you might consider making that naked
11:30 AM exp: you are writing to a global, so i don't think you need to do any stack manipulation
11:30 AM josuah: > decrement by the number of cycles you can statically calculate <- very nice! no branching indeed
11:30 AM exp: yeah using ISR macros does mean that static counting has to be fudged a little bit, but i think naked ones are truly naked
11:31 AM josuah: are ISR under such a high pressure?
11:31 AM josuah: yes, there is the whole register-saving with AVR, (not needed with ARM iirc?)
11:31 AM exp: it's not that exactly, it's that if you include the ISR preamble, you have to include that in your delay calculations
11:32 AM exp: wheras you don't actually require it, and a naked ISR should remove an element of change and remove a 'magic number' from those calculations
11:32 AM josuah: but why would it matter? do I not only need to only count the moment I read from TCNT0?
11:33 AM josuah: s/count the moment I read/count the cycles after I read/
11:33 AM exp: oh sorry, i'm talking here assuming you're using an interrupt to handle an external trigger
11:33 AM exp: if you're just triggering this in a loop then ignore my latest caveats
11:33 AM josuah: ah right!
11:33 AM josuah: still a good one question
11:33 AM exp: trying to think of the various factors to ensure you sample the external signal at the exact right clock value
11:33 AM josuah: I am not there yet (still getting started with embedded at all)
11:33 AM josuah: but it's interesting
11:34 AM exp: it is indeed, i wish i had more time in general
11:35 AM josuah: I could do 0 embedded through my whole 3-year of admin job
11:35 AM josuah: so I am taking 1 year to at least "boot-up"
11:36 AM josuah: then will see what I can do. some embedded job already? need more classes or time? will see...
11:36 AM josuah: so yeah! time comes short!
01:30 PM rue_bed2: why do people make a huge deal about embedded stuff?
01:31 PM josuah: huge deal as in overcomplicating? or putting too much importance?
01:33 PM rue_bed2: seems to be put on a really high pediatal
01:33 PM rue_bed2: pedistal
01:33 PM rue_bed2: not sure why
01:33 PM josuah: if I can do my little embedded stuff in my corner and be forgotten by all I'm happy :)
01:34 PM josuah: good question though
01:34 PM josuah: maybe marketting people believe there is a market for it
01:35 PM josuah: or want to create one at least
01:35 PM rue_bed2: its programmers mostly
01:35 PM rue_bed2: I'm going to learn embedded
01:35 PM rue_bed2: like its the apex of software dev
01:35 PM rue_bed2: ???
01:38 PM josuah: it would rather be the abyss for how low-level it is
01:38 PM josuah: but puns aside, I did not encounter so many people hype on the "embedded"
01:39 PM josuah: maybe some more for "IoT", if that counts as embedded software development
01:39 PM josuah: for me it is the most enjoyable, would not say apex though
01:40 PM josuah: just one weird slice of the software stack where there is fewer on application side and more toward device handling and physical layers
07:25 PM exp: cool tool of today for me, atlc
07:25 PM exp: i needed to calculate the differential impedance of an asymmetric edge coupled coax tl
07:25 PM exp: none of the generic templates match, but atlc you literally draw a bitmap to represent a 2d segment
07:26 PM exp: very cool, very effective
07:27 PM exp: https://i.imgur.com/PqGAO01.jpg
07:27 PM exp: you can see the poured ground plane poking in, and the asymmetry between prepreg l1 -> 2, and core l2 -> 3
07:44 PM Phantom: but it is not 300% more ground plane!
07:49 PM exp: Phantom: i don't know the reference, i'm assuming it's a reference!
07:50 PM Phantom: https://audiophilestyle.com/forums/topic/62753-nvme-ssd-designed-for-audiophiles/
07:50 PM exp: oh dear i don't even want to click based on the url
07:51 PM exp: although my company has recently been looking into what we can manufacture that's relatively high margin
07:51 PM exp: products for audiophiles :D
07:51 PM exp: i *love* the gold caps
07:51 PM exp: i want some
07:52 PM Phantom: you do want to click, to laught at it
07:59 PM exp: Phantom: it used to irritate me that these people exist, but now as a manufacturer i just want to know how to reach them
07:59 PM exp: if they'll pay $10k for a single loudspeaker, i'll be happy to design it to their most rigorous of standards
07:59 PM exp: hell i'll smelt the copper myself
08:00 PM Phantom: yeah it's crazy what they can pay for bad products
08:08 PM qu1j0t3: exp: just make your capacitor as an NFT
08:13 PM exp: qu1j0t3: lool
08:13 PM exp: i've got millions of oscilloscope traces, sorry, unique digital art pieces created by nature
08:14 PM exp: anyway, i have now got two transmission line designs to keep the same impedance to within a % on external and internal layers with only via stubs being the annoyance
08:14 PM exp: don't think eurocircuits offers backdrilling and this isn't impedance controlled so it'll have to do
11:09 PM jmiehe1 is now known as jmiehe