Measuring the cycle of while loop

Thread Starter

andriasm

Joined Aug 2, 2022
25
I have a firmware that has several instructions.
In the main, we have only one repetition structure (for( ; ; )).
If I measure the cycle of this for( ; ; ) with an oscilloscope, I would get some known value (represented on microcontroller datasheet, for example)?
e.g.:

for( ; ; ){
GPIO2 = true;
.
.
.

GPIO2 = false;
}

How can I say which value I must measure with the osciloscope?
I am asking it because I wanna measure if my firmware has a lot of instruction. If it's enought or it's full of instructions.
I must find this ideal value on datasheet? It's the best way to measure if my code has instructions enough?
 

Irving

Joined Jan 30, 2016
3,843
Most microcontrollers have fixed instruction timing which will be given as # of clock cycles per instruction in the data sheet. Most will be the same # clock cycles per instruction but there maybe exceptions - indirect memory addressing for example. Therefore you can calculate the processing time of a given set of instructions. Or you can measure it with a scope as you suggested.

However, unless its for a relatively trivial problem, adjusting/controlling timing by adding/removing instructions is very bad practice. If you want to do something repetitively at a constant time interval you should use a timer interrupt or an external hardware trigger.

Of course if you can't do everything you need to do between interrupts then you need a faster processor.
 

John P

Joined Oct 14, 2008
2,025
I'm not able to understand what you're trying to do here. Could you get someone to help you write English?

If you want to make your loop take a particular length of time, it is possible to do it by adjusting the instructions you use. But as Irving said, it's difficult, and also if you have branches within the loop it's even worse, if you want every branch to take the same length of time. An interrupt, or even polling a timer, would work better.

But I think it's more likely that what you want is to measure the length of time the code takes to run, and using a scope is a reasonable way to do it. Just note that in the code you listed, the output will be in the "true" state almost all the time. That's because when the code reaches the end, the output goes to "false" and then loops back to the start and becomes "true" again. If you put this at the top of the loop, the output would be a square wave where both the high and low times would give you the loop time.
if (i++ & 1)
GPIO2 = true;
 

atferrari

Joined Jan 6, 2004
4,764
I have a firmware that has several instructions.
In the main, we have only one repetition structure (for( ; ; )).
If I measure the cycle of this for( ; ; ) with an oscilloscope, I would get some known value (represented on microcontroller datasheet, for example)?
e.g.:

for( ; ; ){
GPIO2 = true;
.
.
.

GPIO2 = false;
}

How can I say which value I must measure with the osciloscope?
I am asking it because I wanna measure if my firmware has a lot of instruction. If it's enought or it's full of instructions.
I must find this ideal value on datasheet? It's the best way to measure if my code has instructions enough?
Just for the test you intend to implement, make a loop repeating your "for...." above, indefinitely.

You can then measure the width of the pulse (time elapsed between 1 and 0 mesured on that pin).

Just for your reference I am showing here below, the ISR I implemented more than a decade ago to materialize a 1 ms tick based on TIMR2 (PIC18F family). Every time I implement a fresh piece of software with a micro, the first thing I check is the pin (PIN_DEBUG). If I see on the scope brief pulses ocurring every ms, the basic is OK.

For very specific situations I just toggle that pin when starting / completing the ISR.

Code:
  ;017_ISR_HIGH.S

  Psect code
  global UPDATE_TIME_BASES,TBASES_UPDATE_DONE
;------------------------------------------------------------------------------

;High priority interrupts service routine
;Interrupts desabled. STATUS, W & BSR saved automatically in the fast stack.
;------------------------------------------------------------------------------

  PIN_DEBUG_HI                  ;pin DEBUG set to show activity
;------------------------------------------------------------------------------

;actual interrupts service code starts here

UPDATE_TIME_BASES:              ;informative labe
  BSF TBASE_FAST_ELAP,A         ;show "fast time base period elapsed"
  DECFSZ CNTR_TBASE_SLOW,A      ;decrement the slow time base counter
  BRA TBASES_UPDATE_DONE        ;not =0 yet - period not elapsed - leave!

  LOADREG_IN_ACC CNTR_TBASE_SLOW,COUNT_TBASE_SLOW
;slow timebase period = (fast timebase period * COUNT_TBASE_SLOW)

  BSF TBASE_SLOW_ELAP,A         ;=1 means "slow time base period elapsed"

TBASES_UPDATE_DONE:
  BCF TMR2IF                    ;=0 clears TMR2 flag prior returning

;actual interrup service code ends here
;------------------------------------------------------------------------------

  PIN_DEBUG_LO                ;pin DEBUG reset to show activity
;------------------------------------------------------------------------------

;STATUS, W & BSR ARE retrieved from the fast stack.
  RETFIE F                   ;back to main line code - interrupts enabled.
 
Last edited:

DickCappels

Joined Aug 21, 2008
10,153
I usually measure timing loops in the simulator that comes with the integrated development environment (IDE) for that controller. Toggling I/O is useful for things like triggering a scope so it knows when to capture a waveform.
 

trebla

Joined Jun 29, 2019
542
I am asking it because I wanna measure if my firmware has a lot of instruction. If it's enought or it's full of instructions.
I must find this ideal value on datasheet? It's the best way to measure if my code has instructions enough?
The code has enough instructions if it does what is desired. You can reduce code size if you use more functions instead of repeated code blocks with same functionality.
 

djsfantasi

Joined Apr 11, 2010
9,156
This code does not toggle the pin, after first time being true it stays high. Add reset line too:

C:
if (i++ & 1)
  GPIO2 = true;
else
  GPIO2 = false;
It does toggle the IO pin. When i is even, the pin would be set to false; when i is odd, the pin would be set to true.
 

Irving

Joined Jan 30, 2016
3,843
It does toggle the IO pin. When i is even, the pin would be set to false; when i is odd, the pin would be set to true.
I think what the others have missed is that it works as you say because of the existing GPIO2 =false; at the end of the loop. In isolation it doesn't work.

Personally I'd put

GPIO2 = (i++ & 1);

at the top of the loop, and remove the line at the bottom.
 
Last edited:

wraujr

Joined Jun 28, 2022
160
Similar to what others suggested:

for (i = 1 ; i <= X ; i++ ) {
GPIO2 = (i & 1); // uses LSB of i as toggle
.
.
}

Set o-scope to "single" trigger on rising-edge of GPIO2 and start loop running.
The amount of time during the first pass thru loop will be time GPIO2 is high.
Depending on processor and cacheing, this "high" time may be longer than subsequent periods.
By writing GPIO2 once you get all execution time including the "for loop" execution.
Second pass thru loop will be the GPIO2 "low" time.
Comment out line when done timing checks.
Calculating # of instructions in a loop from this period and knowing clock freq can be simple for some
ARM like processors, but more complex for advanced processors.

Or look at disassembly code and count the instructions in a loop.
 

Jerry-Hat-Trick

Joined Aug 31, 2022
544
I'm wondering if the old technique I learned at school would work - to measure the thickness of a piece of paper put 1,000 pieces together and measure the thickness and divide by 1,000.

So in this case, maybe turn an LED on when you start the loop, make the loop run a very large number of times, and turn the LED off at the end, timing with a stop watch. This will give you good precision. If you put the loop within another loop so the total loop count is the product of the two it will be even better

Hope I've understood what you are trying to do....
 

Ya’akov

Joined Jan 27, 2019
9,069
I'm wondering if the old technique I learned at school would work - to measure the thickness of a piece of paper put 1,000 pieces together and measure the thickness and divide by 1,000.

So in this case, maybe turn an LED on when you start the loop, make the loop run a very large number of times, and turn the LED off at the end, timing with a stop watch. This will give you good precision. If you put the loop within another loop so the total loop count is the product of the two it will be even better

Hope I've understood what you are trying to do....
This is a very good technique to arrive at an average but of course can’t tell you the individual items or events and how they differ. The measurement will be off for any given single item by the deviation possible for any single item, something you can’t know form this technique.

(In some cases this might already be known thanks to more expensive single item measurement allowing you to know the error band you are dealing with.)
 

Jerry-Hat-Trick

Joined Aug 31, 2022
544
This is a very good technique to arrive at an average but of course can’t tell you the individual items or events and how they differ. The measurement will be off for any given single item by the deviation possible for any single item, something you can’t know from this technique.
Fair point, although if it's doing the same instructions it'll be pretty much the same - possible to tell from the code. If it has conditional branches/instructions it'll vary of course - but surely the same problem if you are looking with a 'scope? I'm more experienced with hardware than code but with a Seeeduino XIAO which runs pretty fast I've used T1 = micros(), for loop, T2 = micros, T = T2 - T1 to know the time a loop takes - in particular to check whether I've missed a crank trigger wheel input which happens at regular intervals. Untidy, but it worked!
 
Last edited:

Irving

Joined Jan 30, 2016
3,843
I'm wondering if the old technique I learned at school would work - to measure the thickness of a piece of paper put 1,000 pieces together and measure the thickness and divide by 1,000.

So in this case, maybe turn an LED on when you start the loop, make the loop run a very large number of times, and turn the LED off at the end, timing with a stop watch. This will give you good precision. If you put the loop within another loop so the total loop count is the product of the two it will be even better

Hope I've understood what you are trying to do....
Conceptually that's exactly what the TS is trying to do. Of course the MCU has a much more accurate timer built-in than a stop-watch accurate down to a few uS on an Arduino. The basic code is...

Code:
#define MAXCOUNT 10000

void loop(){
  ulong now = 0;
  ulong then = microseconds();
  for(ulong count=0 ;count<MAXCOUNT; count++)
    {

    //code to be timed

    }
  now=microseconds();
  Serial.printf("Time for %lu iterations = %lu uS. time for one iteration = %lu uS\n".MAXCOUNT, now-then, (now-then)/MAXCOUNT);
}//end loop
Knowing something of the TS' requirement from other threads I'm guessing he needs a chunk of code that will execute in around 2 - 5mS (200 - 500 times/second) leaving time for other activity. Easily do-able and bettered with a modern MCU (preferably 32bit, not an original Arduino however).
 
Top