Delays

General discussions about working with the Astrobe IDE and programming ARM Cortex-M0, M3, M4 and M7 microcontrollers.
Post Reply
steve64
Posts: 43
Joined: Mon Jul 09, 2018 8:56 am
Location: Italy

Delays

Post by steve64 » Wed Sep 05, 2018 12:29 pm

How much precise is the Timers.Delay() in terms of the generated wait interval
when using a timer initialized with Timers.uSec as unit?

Also, is there a way (by other means) to generate a specific delay below 1 us ?
I can guess something like a FOR loop with EMIT passing a NOP instruction...
(clearly would be CPU clock dependent but could be acceptable for this use case).

cfbsoftware
Site Admin
Posts: 493
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Delays

Post by cfbsoftware » Wed Sep 05, 2018 2:23 pm

The following code counts the number of 1000 uSec delays that occur during 1 second of time as recorded by the real-time clock. It returns exactly 1000:

Code: Select all

  Clock.Init();
  secs := 0;
  Clock.SetHMS(0, 0, 0);
  count := 0;
  REPEAT secs := Clock.Seconds() UNTIL secs = 1; 
  WHILE secs # 2 DO
    Timers.Delay(usecTimer, 1000);
    INC(count);
    secs := Clock.Seconds();
  END; 
  Out.Int(count, 0); Out.Ln();
If the delay is reduced to 100 uSec the result is 9945 not 10000 because the overheads of executing the loop start to become a more significant factor. If you want to get a more accurate measurement you could use a 1 uSec delay to toggle a GPIO pin and look at the resulting pulse on a scope.

Yes, you could use an empty loop to get much shorter delays that are dependent on your clock speed. e.g. the following code in a leaf procedure executes 3 * x + 1 instructions.

Code: Select all

  i := 0; REPEAT INC(i) UNTIL i = x;
I thought that equated to (3 * x + 1 nanosecs) for a 100MHz clock. However, when I ran the following at 216 MHz on a Cortex-M7 it executed in exactly 2000000 uSecs not 3000000 uSecs as I expected. Maybe I've misunderstood something?

Code: Select all

PROCEDURE* Delay(n: INTEGER);
VAR
  i: INTEGER;
BEGIN
  i := 0; REPEAT INC(i) UNTIL i = n
END Delay;
  
PROCEDURE Run;
VAR
  i, elapsed: INTEGER;
BEGIN 
  Timers.Start(usecTimer);
  Delay(216000000);
  elapsed := Timers.Elapsed(usecTimer);
  Out.Int(elapsed, 0); Out.Ln();
END Run;

steve64
Posts: 43
Joined: Mon Jul 09, 2018 8:56 am
Location: Italy

Re: Delays

Post by steve64 » Wed Sep 05, 2018 3:54 pm

The Cortex M7 used in the STM32 MCU has a six-stage dual-issue pipeline.
So I guess that that loop is executed faster than expected for such reason.

Thanks for all the info on timing.

steve64
Posts: 43
Joined: Mon Jul 09, 2018 8:56 am
Location: Italy

Re: Delays

Post by steve64 » Thu Sep 06, 2018 8:16 am

There's a strange behavior in my environment (Cortex M7).
Let try the following test. It takes 5 seconds whatever the CPU clock.
I also performed a HW reset before each run with different clock.

Maybe I'm missing something...

MODULE SpeedTest;

IMPORT Main, LinkOptions, Out, Clock;

VAR
i, x, secs: INTEGER;

BEGIN

Out.String("CPU Frequency: "); Out.Int(LinkOptions.Fosc, 0); Out.Ln;
Clock.Init();

Out.String("measuring..."); Out.Ln;
secs := 0;
x := 100000000;
Clock.SetHMS(0, 0, 0);
i := 0; REPEAT INC(i) UNTIL i = x;
secs := Clock.Seconds();
Out.String("elapsed (s): "); Out.Int(secs, 0); Out.Ln;

END SpeedTest.

cfbsoftware
Site Admin
Posts: 493
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Delays

Post by cfbsoftware » Sat Sep 08, 2018 6:00 am

(Sorry - I accidentally overwrote your previous reply)

You can use the Crystal Freq (Hz) parameter if you want to target boards with different clock frequencies. You could then use the value to set all of the appropriate clock parameters in Main.mod. You would also need to put checks in your code to report if an non-applicable frequency has been chosen. As both of the Cortex-M7 boards currently supported have the same clock frequency (8 MHz) none of that additional complexity was necessary. Consequently If you use the default code supplied with Astrobe with the currently supported boards it doesn't matter if you change the value on the configuration form because it is ignored.

According to the STM documentation you should be able to confirm that the CPU is running at the max speed (216 MHz) by monitoring the oscillator outputs MCO1 or MCO2. For details refer to Chapter 5 Reset and clock control (RCC) in the RM0410 Reference Manual for the STM32F76xxx and STM32F77xxx, and the UM1974 User manual for the STM32 Nucleo-144 boards. Unfortunately I have had no success with that - I'm probably just missing one of the many parameters that you need to take care of. The next best thing I could do was measure a waveform on GPIO pin PF13 which was generated using 7 instructions with the following minimal code:

Code: Select all

PROCEDURE* Run;
CONST
  GPIOFBase = 040021400H;
  GPIO_BSRR = 018H;
VAR
  on, off: SET;
BEGIN
  on := {13};
  off := {29};
  WHILE TRUE DO
    SYSTEM.PUT(GPIOFBase + GPIO_BSRR, on);
    SYSTEM.PUT(GPIOFBase + GPIO_BSRR, off);
  END 
END Run;
That resulted in a frequency of 36 MHz which is higher than I would have expected. I would have thought that you would need only six instructions to get that rate so the pipeline you mentioned must be having an effect.

cfbsoftware
Site Admin
Posts: 493
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Delays

Post by cfbsoftware » Sat Sep 08, 2018 7:40 am

cfbsoftware wrote:Unfortunately I have had no success with that - I'm probably just missing one of the many parameters that you need to take care of.
Duh! I wasn't missing a parameter I just had Pin PC9 mode configured as Output Mode rather than an Alternate Function Mode.

The MCO2 frequency on Pin PC9 measures as 43.2 MHz. That is exactly what it should be for a 216 MHz clock as the relevant RCC_CFGR values are set in Main.mod as follows:

Bits 31:30 MCO2 = 0 (Clock source = SYSCLK)
Bits 27:29 MC02PRE = 111 (MCO2 prescalar = division by 5)

If you want to try it yourself, this is the code you need:

Code: Select all

GPIO.Map(PORTC, 9, MCO2);
ConfigurePin(MCO2, GPIO.Mode_AF, GPIO.AF0);

steve64
Posts: 43
Joined: Mon Jul 09, 2018 8:56 am
Location: Italy

Re: Delays

Post by steve64 » Mon Sep 10, 2018 9:57 am

Thanks a lot, great help from you as usual.

Post Reply