This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Maybe I'll have to create a launchpad software to show the point, but here's an attempt in words:
- A PWM signal is received in a TCCP pin
- The period of the signal is about 1ms, and it is non-stop
- Timer A0 is configured to capture the signal on BOTH EDGES. DMAEventSet is properly configured to CAPEVENT
TimerConfigure(TIMER0_BASE,(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP)); //TimerPrescaleSet(TIMER0_BASE, TIMER_A, ENC_PRESCALER); TimerPrescaleSet(TIMER0_BASE, TIMER_A, prescale); TimerLoadSet(TIMER0_BASE, TIMER_A, 0); // Was 0xFFFF TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_BOTH_EDGES); TimerDMAEventSet(TIMER0_BASE, TIMER_DMA_CAPEVENT_A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_DMA | TIMER_TIMA_TIMEOUT); IntPrioritySet(INT_TIMER0A, 0); // The highest possible interrupt IntEnable(INT_TIMER0A);
Note that there is an attempt to enable TIMEOUT as an interrupt source here - which does not happen - but that's still not the discussion right now, I'll get back to it.
When I want to measure the PWM, I configure the DMA channel:
uDMAChannelAssign(UDMA_CH18_TIMER0A); uDMAChannelAttributeDisable(UDMA_CH18_TIMER0A, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelControlSet((UDMA_CH18_TIMER0A|UDMA_PRI_SELECT),(UDMA_SIZE_32|UDMA_SRC_INC_NONE|UDMA_DST_INC_32|UDMA_ARB_1)); uDMAChannelTransferSet((UDMA_CH18_TIMER0A|UDMA_PRI_SELECT), UDMA_MODE_BASIC,(void *)(TIMER0_BASE + 0x048),encoderPulses,4); uDMAChannelEnable(UDMA_CH18_TIMER0A); // Enable this particular channel HWREG(TIMER0_BASE + TIMER_O_TAV) = 0; // Zeroes timer counter ROM_TimerEnable(TIMER0_BASE, TIMER_A); // Enables timer0 so that signal is captured
This is enough to get the internal gears running - and 4 edge moments should be transferred via DMA from a fixed TMER0 TAR register into a incrementing array encoderPulses.
It works as expected, but very often I get weird sequences, like:
2 350 396, 2 397 921, 54 350, 101 754
Clearly, the timer counter rolled over. That's (supposedly) impossible on this system, the signal remains running all the time, and the first 4 pulses should be recorded. If I add the timeout load to the smaller values (in this particular configuration, that's 37*2^16), I obtain perfect continuous values that reflect the actual signal. A proper sequence is something like:
1 084 102, 1 131 633, 1 212 768, 1 260 302
Still, the sequence above shows that the 4 recorded values were DMA-transferred kind of LATE! If the signal is ~1ms, the first event must have happened in less than 120000 clicks after TAV is loaded to zero and TimerEnable is set.
Is there some DMA mistake on my configuration or errata that I am missing?
Regards
Bruno
Bruno Saraiva said:Transfer insanity - or mine?
You've "baited" us "too far" to let this go - if "insanity" can be measured by the (frequency) of those appearing - your facility - clad in "Med White" - armed w/"Restraints" & "escorting" you away - then "Yes" that "insanity" (may) be yours. (indeed - famed poster/student Luis, "squealed!")
What may "better" demonstrate "insanity" (or at least - huge inconsistency) is the SINGLE, UNEXPLAINED APPEARANCE of a "ROM Function" (ROM TimerEnable()) - while all other functions are (content) w/in Flash.
Now you specifically note: (below)
Bruno Saraiva said:first event must have happened in less than 120000 clicks after TAV is loaded to zero and TimerEnable is set.
As firm/I work w/many ARM MCUs - I cannot recall if your "call to ROM" (here) was deliberate - and is justified by offering (maybe) more deterministic behavior/response. Thinking further - even if the "Onset of the Timer Enable proves "variable" - it is the "difference in time" - between your 4 consecutive signal arrivals which is sought - not their "offset" from Timer Enable. (is this a correct understanding, Bruno?) In any event - the (lone) inclusion of the ROM function seems unusual - thus suspect.
On a second note - you have often commented upon (and written here) to the abundance of Timers w/in these MCUs. Yet - Timer A0 has received the "exclusive & full force" of your application! Is that wise - especially as you've noted "issues?" Might the employ (instead) of at least another Timer - or that number of Timers which "simplifies & lightens the load upon each Timer" - provide a "more insightful" path?
We note that, "Following the same (failed) path" is one indication of (your word) "insanity." The ability to "cross-correlate" (i.e. compare the tightly organized data provided by multiple timers) - each charged w/ a specific, limited function - provided here (only) thru the use of multiple Timers) - appears worthy of consideration... (and maybe (even) restores sanity ...)
Robert Adsett72 said:Why is timer rollover impossible?
Indeed the 120,000 (1mS) Timer Counts will "over-flow/roll-over" 16 bit Timer0A. But - poster Bruno has added the "8 Bit Prescaler" to the mix. (w/out mention of its value) Thus - i calculate "roll-over" to (potentially) extend to 140mS. (assumes the prescalar set to max value ... 16,777,216 / 120,000,000 where 16 million is 2^24 (max value for timer & prescalar) & 120 is system clock) By quick-calc - a minimum Prescale load of "10" is required to extend roll-over to 5mS (i.e. 120K -> 1mS, 600K then-> 5mS). This 5mS provides a (substantial) safety factor (in accommodating 4 signal edges) - I believe.
Now - w/his input signal @ 1mS periods - and provided he has (fully/properly) zero'ed his 24 bit Timer - he cannot (or should not) over-flow the Timer.
Again - w/out knowing the Prescalar's setting - i believe our ability to predict "roll-over" is indeterminate.
It would appear that the Prescaler setting/management is improper - OR - that the Timer is "free-running" (not zero'ed) - and on occasion - the 4 input signal edges occur too close to "Timer-MAX Value" - and thus roll-over occurs...
It is my belief that (both) Timer0A and its Prescalar (must) be zero'ed - prior to each (new) "Data Capturing/Timer Enabling." Any "zeroing" of the Prescalar is NOT shown in B's code. (record should note that I've based much herein upon my review of the TM4C123 manual - only one I have available - at this moment.)
I cannot find any explicit Prescale setting - which to me - greatly impacts the rollover period.
I find the following:
//TimerPrescaleSet(TIMER0_BASE, TIMER_A, ENC_PRESCALER);
TimerPrescaleSet(TIMER0_BASE, TIMER_A, prescale); // value of variable "prescale" is nowhere I can find!
And further down the post he writes, "If I add the timeout load to the smaller values (in this particular configuration, that's 37*2^16..." This suggests that "37" is the value he's loaded to the Prescaler. (as the Timer alone holds 16 bits). This yields a final Timer value of "2,424,832" which creates a rollover of 20mS. I can find no justification for how that (large) value was chosen.
Looking at Bruno's "good"numbers: "1 084 102 [1] 1 131 633 [2] 1 212 768 [3] 1 260 302 [4]" and recalling that any two (same) edges are "3 readings separated" (i.e. "H-L-H-L") we find:
I've looked - yet cannot find the "value for rollover" w/in his post... In the effort to "divine" that rollover - here is Bruno's "failing sequence" (below) of Timer captures:
2 350 396 [1[ 2 397 921 [2] 54 350 [3] 101 754 [4]
I've taken the liberty to highlight measure "3" (above) - which is the likely "rollover" victim. Generalizing from the correct readings (higher above) we'd expect measure [3] to be ~128K Timer Counts greater than measure [1]. (putting it at/around 2,479,000) This indicates that a rollover (on this occasion!) occurred somewhere between 2,397,922 (1 greater than measure [2]) and (perhaps, 128,000 - 54350 = 73,650 Timer Counts beyond measure [2]. (that would be ~2,471,571) (maybe) Does this agree w/your thought process, Robert? Still - I cannot accept that "Bruno gave such rollover value."
Looking (and thinking) further re: Bruno's failed sequence - "How did the Timer Counter (ever) rise so high?" (And it rose high in the "Good Sequence" too!) This must mean that the Timer/Prescaler combo is "Not being cleared to zero" - prior to each new, 4 input signal measure - and is thus subject to rollover at/about the 20mS rollover setting! With a (proper) Timer/Prescaler "clear" - any such rollover (only then) would be "unlikely."
We may note that the rollover is "easily detected" - and if we can "live with" the expectation that the input PWM signal maintains its duty cycle & frequency - the math I've employed here enables the MCU to avoid (both) Timer & Prescalar Resets - should those operations be disruptive and/or unwanted...
And of course - by fully loading the Prescaler (i.e. to 255) - the frequency of such rollovers can be reduced by better than a factor of SIX! (i.e. 255/37)
I believe the issue has been identified & 2 solutions proposed... (properly reset the Timer/Prescaler combo - or extend the Prescaler setting to max.)
Robert Adsett72 said:in my experience prescalers are divide by n devices not extenders so does the prescaler really just act as an extension?
My experience overlaps yours - here's a quote from my MCU manual: "16-bit input-edge count- or time-capture modes with an 8-bit prescaler" - now that's not especially telling - but the chart (below) is!
Edge time appears 2nd from the bottom - and the Prescaler is listed as an "extender" and contains the high-order 8 bits. Thus the Timer contains the lower 16 bits - the Prescaler the upper 8 bits. Some Timers - to include the very one Bruno chose - "can & do" accommodate 32 bits - and the Prescaler then expands to include the upper 16 bits! Had the Timer been forced into "wide Timer mode" - the rollover potential is significantly reduced. That said - I believe it best to clear the Timer/Prescaler combo just prior to Enabling that pair.
You've asked about the "timer read" - Timer_0A's lower 16 bits are the only ones valid - the full 32 bits come into play when config'ed as wide timer. And yes - when that timer can be (via program) "split from 32 bits into 2 16 bit timers. But the Prescaler is NOT in the top order - it resides in a separate (prescaler) register. The "independence" of the Prescaler from the Timer is why I believe separate "clears" are required for both. (firm/I do not use 129x - so this all results from my 4C123 experience & manual read.)
Good day cb1 and Robert,
What a beautiful set of weekend thoughts you provided! Thank you very much. Indeed, I guess my title-bait was spot on!
Trying to get back to all considerations in just one message:
1) ROM_ calls: it was just an "accident". We tend to leave flash calls during development, and then when all is good, replace them by ROM_ calls (or actually, MAP_ ones). The original code before I posted had lots of MAP_'s, but one stray ROM_ entry, and I erased them to paste in the message, for I prefer to keep "pure" Tivaware when writing here.
2) Abundance of timers: the rest of the engine uses other timers - including one to control the PWM signal timeout, triggered in case the hardware isn't connected or fails. More on this below. But the use of DMA restrains the automatic capture of event times to one origin, so things become a bit hard to debug using other timers as references/comparisons. By the way, I succeeded to use two DMA origins triggered by the same time-capture event, but that was at cost of two DMA channels - which was only available in one of the pins. So in this particular board, I am using the DMA only to copy the timer event, and "running" to read the GPIO value after capture #4. If anyone knows how to enable a second DMA origin/destination set in the same configuration, it will be welcome!
3) The rollover is not inevitable NOR expected. The ENC_PRESCALER is set to decimal 37. The "excessive number" was on purpose, exactly to try to obtain a timeout after 20ms (well calculated, cb1!). The timer0A free running value is zeroed before each capture cycle, via HWREG(TIMER0_BASE + TIMER_O_TAV) = 0 right before the timer is enabled. Then, another question arises: is it REALLY not possible to obtain BOTH the DMA transfer for each capture event - which is (almost) perfectly happening - AND the timer timeout, using the settings presented?
4) Which values matter? Yes, I am concerned with the elapsed time between events, not with the values from timer start. And yes, they are exactly H-L-H-L (or L-H-L-H) counts.
5) Where is the rollover? Precisely where cb1 marked red on his post. Values [3] and [4] of the "bad" sequence. The prescaler is set at 37, so the timer runs all the way to 2424832 before coming to zero. Let's look at the numbers again:
2 350 396 [1] 2 397 921 [2] 54 350 [3] 101 754 [4]
If we add that prescale to the rollovered values, we get
2 350 396 [1], 2 397 921 [2], 2 479 182 [3] , 2 526 586 [4]
In which both the elapsed times [3]-[1] and [4]-[2] are ~128700, as expected.
6) All things considered, it seems that the failure is on not zeroing the timer counter AND the prescaler... in fact, I was not zeroing the prescaler, only the free-running counter. Funny enough, there are entries somewhere in the datasheet saying BOTH are automatically zeroed when timer is started, which is not correct - I'll seek such text to confirm my statement, and if so, will post it back here.
7) Robert, the remained post seems to have clarified your question - but indeed, the prescaler here acts like an extender. Free counter goes from zero all the way to the "main" timer load, when two things happen: prescaler is incremented and free-counter goes to zero, continuing to count. Timeout is expected only when prescaler reaches its own load.
8) The timer is read as a 32-bit value: in fact, that's how it is! The TAR register contains a "32 bit" value formed by 8 MSB zeroes, another 8 bits with the prescaler count, and then 16 bits with the "main" free running timer. I learned this only a couple of weeks ago, and it kind of struck: the whole description of the MCU having (let's say 16x) 16-bit timers is misleading. It actually has 16x 24-bit timers! I prefer now to say that, because if you read the counting register (provided that you configured the prescaler with some value first), you get 24 bits of counted clicks... Marketing/sales people are "wasting 8 bits" on their sales pitches!
I'll do some tests now and get back here. Just found another conflicting piece of information on the Register 14 (GPTMTAPR) description of the datasheet: it says that bits 31-8 are RO, and that bits 7-0 are RW... How on earth can I write only the lower 7 bits of a register??? I will probably be able to write into the full register, and I guess that the RO bits will remain 0 despite what we write there - but still, it is "interesting" to call them RO...
Hope I did not forget any feedback for now.
Thanks again, more soon!
Bruno
Well, I've got some more news...
The rollover is INDEED due to the fact that the Prescaler counter has not been zeroed. Consecutive register visualizations of TAPS after each capture cycle shows that the counter keeps going up all the way to the 0x25 load value stored in TAPR.
Despite the fact that the TAV register has both the prescaler (bits 23-16) and the timer counters (bits 15-0), writing 0 to TAV does not zero the prescaler counter (fair enough, the actual counter register is somewhere else, named TAPS...)
BUT, the register TAPS register IS READ ONLY, writing to it causes no change. In other words, this seems to be a dead end, there is no way to zero the prescaler. TEXAS INSTRUMENTS folks?
I can easily solve my issue just loading the Prescaler all the way to 0xFF, and checking for a rollover on the captured measurements... but still I'd like to see if I'm missing something here!
As for the "once sentence reply" to the post question, the winner is:
cb1_mobile said:It is my belief that (both) Timer0A and its Prescalar (must) be zero'ed - prior to each (new) "Data Capturing/Timer Enabling."
Greetings Bruno & thank you for the effort you've expended in (really) reading the (few) posts of Robert et moi.
Bit late last night - but I found this morn:
"In the16-bit Input Edge Count, Input Edge Time, and PWM modes, bits 15:0 contain the value of the counter and bits 23:16 contain the value of the prescaler, which is the upper 8 bits of the count. Bits 31:24 always read as 0." This aimed at Register, "GPTMTAR." And Bruno - this is just as you found & reported - your first post (here) today.
As the "identifier" of the, "Requirement to zero the Prescaler" - might some "flow of green" prove warranted? (my firm's stock of "low thread count T shirts" (& Eval boards) ... (now) "blocks the sun!")
One more issue for you to consider - depending upon your accuracy requirement - I'd suspect that (far) more than, "four such edge-time captures" are necessary. Indeed 4 captures occur quickly - but rogue pulse widths/pulses - will (unduly) impact your accuracy. As you know - the "trade-off" here is "frequency of data acquisition vs accuracy (averaging) of such acquisition." Only you know the (proper) weight of each...
Neat post - you may wish to (somewhat) quiet the, "reporting by Luis." (my small group, "saw him first.")
Bruno Saraiva said:but still I'd like to see if I'm missing something here!... TEXAS INSTRUMENTS folks?
While far (very far) from "hallowed vendor status" may that "missing something" be "filled" via Timer Register, "GPTMTAPR"? (that's the Timer_A Prescaler Register)
The lower 8 bits of that register are R/W - thus (should) enable your "regular & proper" Prescaler clearing.
Pity that the vendor code examples appear "too basic" - and rarely reach, "Deep Dive" status! (which you (and others here) are likely to grow to - and then require!)
Might it be possible that "vendor only" - proves not (always) "best/only port" (as you suggest, via "folks" plea) - when storm clouds arise? (Lightning just struck...)
cb1_mobile said:The lower 8 bits of that register are R/W - thus (should) enable your "regular & proper" Prescaler clearing.
cb1,
That's the tricky point: GPTM-TAPR is NOT the prescaler counter, but rather, the prescaler "limiter", or load. Timer/prescaler count all the way to TAILR/TAPR and rolls.
The register that holds the current prescaler value is TAPS, offset at 0x5C. That's what would need to be zeroed before a cycle. And such folk is RO. Unless TI proves me wrong, it is not possible to clear the prescaler counter.
This was the desired command:
HWREG(TIMER3_BASE + TIMER_O_TAPS) = 0; // #define TIMER_O_TAPS 0x05C
And a further comment to Timer management: there is obviously no Tivaware function for this (as it is a RO register), but there should be a Tivaware function to read/write the timer free counter, which does not exist. I often use the following DRM:
HWREG(TIMER3_BASE + TIMER_O_TAV) = 0; // #define TIMER_O_TAV 0x050
To add some salt, the Tivaware documents does not make it clear that when you read a timer value with TimerValueGet, you are actually reading TAR (the function header and some UG text wrongly suggests that the function returns the current value of the timer, but that is not always true).
Regards
Bruno
Hi cb1,
You do get a flow of likes, but as for the green, I rather stamp it just on the post which contains the real cause (albeit one that apparently can't be solved).
As for the accuracy, this post is just "a picture". The movie is much longer than that:
- the sensors are continuously measured (~100Hz), extreme values are discarded as unreliable, and still after all that, a moving average is applied. Worth mentioning is that the rate of unreliable captured values is very close to zero...
Cheers!
Bruno
Bruno - may I ask if you've (really) tried to "clear" GPTM-TAPR - and then noted the results?
From past experience w/"pre-ARM" MCUs - the Prescalers did NOT behave as "incrementing/decrementing" counters - instead they merely served as a "Timer divider." But here - operating w/in your selected, "Edge Timer" mode - they (Prescalers) now appear to behave as "Timer Extenders" only - and if they cannot easily be "cleared" - the "Edge-Timer" feature of the MCU has been compromised.
The MCU manual offers: "In input edge count, input edge time and PWM mode, the prescaler always acts as a timer extension, regardless of the count direction." Vendor's tech writer did not know - or was too rushed - to (properly) detail the (full) operating results & implications - imposed by the (somewhat cryptic) "timer extension" label...
Earlier you wrote of reading (somewhere) of the ability to "clear (both) the Timer & Prescaler." I believe that is described w/in the "GPTM Reset Conditions" - below is an (almost) "true copy:" (i.e. I've edited so as to (only) present those Timers/Prescales useful to this post.)
GPTM Reset Conditions
After reset has been applied to the GPTM module, the module is in an inactive state, and all control registers are cleared and in their default states. Counters Timer A and Timer B are initialized to all 1s, along with their corresponding registers:
Timer Registers are initialized to all 1s:
GPTM Timer A Interval Load (GPTMTAILR)
GPTM Timer A Value (GPTMTAV)
Prescale counters are initialized to all 0s:
GPTM Timer A Prescale (GPTMTAPR) note: R/W
GPTM Timer A Prescale Snapshot (GPTMTAPS) note: RO (read only) Ratz!
GPTM Timer A Prescale Value (GPTMTAPV) note: RO (read only) Ratz!
Use of this GPTM Reset appears, "beyond Brutal" - and even if it (does) clear the Prescaler - does so @ significant cost/effort.
Use of the Timer's 32 bit mode - "swallowing" your Timer0_B - while not eliminating roll-over prospects - pushes them (far) into the future... The "test for roll-over" must be performed upon (every) data read - adding to code size & data acquisition's execution time. (neither of which appears substantial - yet the absence of "Prescale Clear" - especially (even) its "FAILED MENTION" still smarts...)
cb1_mobile said:may I ask if you've (really) tried to "clear" GPTM-TAPR - and then noted the results?
I believe I have. TAPR is the one set to decimal 37, and it sets the maximum count of the prescaler. I tried a bunch of combinations, but this one has failed to be on my notes - still, for all I can see here, setting TAPR to zero and then back to 37 before I start the timer again did not bring TAPS to 0.
As mentioned, the program is properly running with a trusted setting now, and "far different" now for a quick test. I might get back to doing a test when I have time for that - in which case, I'm planning to use a bare launchpad generating the PWM in a port, and wiring the signal across to the TCCP pin to measure an easy and known signal.
cb1_mobile said:imposed by the (somewhat cryptic) "timer extension" label...
Mostly ALL of the terminology on the Timers instructions are cryptic. Writer does not keep a consistence across chapters, registers, comments. Words like counter, current, load, extension, value, prescaler, true, divider, get conflicting and confusing. I guess that's their problem, somewhat not mine anymore as I got (most of) the real behaviors... Would have of coursed save valuable time, but well... I feel like vendor here knows all that and has "certainly decided to publish an ultimate version 'next year'"!
cb1_mobile said:Use of this GPTM Reset appears, "beyond Brutal"
I strongly believe THAT would clear the prescaler count - and indeed that's brutal. Certainly not something I want to do 400 times a second or so...
In the end, I'm using the prescaler at full 8 bits, so I have a 24 bit timer. If I need to eventually check rollovers for 24-bit, that's the same for 32, so it won't make a difference - I can live with the extra 2 cycles of load/compare... If I had'n done that, the "absurd values" protection would still catch it - at the cost of a dismissed read cycle. Anyway, pros and cons for all choices...
Only sour taste here is that we still have zero input from our official fellows! Other than that, this post became a nice timer study for victims of the future, don't?
Cheers
Bruno
Bruno Saraiva said:If I need to eventually check rollovers for 24-bit, that's the same for 32, so it won't make a difference
That should be a precaution you take in any case. No?
Robert
Robert Adsett said:Bruno SaraivaIf I need to eventually check rollovers for 24-bit, that's the same for 32, so it won't make a differenceThat should be a precaution you take in any case. No?
It's also a simple masking operation after subtraction. Quite easy in C, you should try to deal with it in ladder logic :)
Robert
Bruno Saraiva said:Not in the mood for thinking right now
:)
Bruno Saraiva said:I believe it ain't that simple if controlling 32 bit rollover...
You're right, it's simpler.
As long as you have a 32 bit data type the compiler will deal with it automatically. Technically it has to be unsigned but I've never seen signed cause a problem. In the case like Cortex where 32 bit is the native size the hardware takes care of it. You don't even need a mask.
Robert