Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: T4 , set_arm_clock and micros()?

  1. #1
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,367

    T4 , set_arm_clock and micros()?

    I get wrong values using micros() after changing CPU speed with set_arm_clock on a T4.
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    void setup() {
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
      set_arm_clock(24000000); // comment here to get full speed
    #endif
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
     static uint32_t t0;
     if(millis()>(t0+1000))
     {
       t0=millis();
       uint32_t t1=micros();
       delay(50);
       Serial.println(micros()-t1);
     }
    }
    this code gives me 1050 as printout
    when commenting the clock change I get the correct value of 50000

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,967
    Quote Originally Posted by WMXZ View Post
    I get wrong values using micros() after changing CPU speed with set_arm_clock on a T4.
    ...
    this code gives me 1050 as printout
    when commenting the clock change I get the correct value of 50000
    @Paul - you'll recognize something here in a flash ... clock change order not leaving millis() clock right?

    Interesting - the problem is millis() when the clock drops - if it drops in the RIGHT order the CLOCKS change over - if not millis() is broken:
    Code:
     F_CPU=600000000	deg  C=32
    	50ms delay:: 50000 us and 50 ms
     F_CPU=240000000	deg  C=33
    	50ms delay:: 50000 us and 50 ms
     F_CPU=110000000	deg  C=32
    	50ms delay:: 1010 us and 1 ms
     F_CPU=24000000	deg  C=30
    	50ms delay:: 50006 us and 50 ms
     F_CPU=600000000	deg  C=30
    	50ms delay:: 50000 us and 50 ms
     F_CPU=129600000	deg  C=34
    	50ms delay:: 50001 us and 50 ms
     F_CPU=110000000	deg  C=32
    	50ms delay:: 50002 us and 50 ms
     F_CPU=24000000	deg  C=31
    	50ms delay:: 50006 us and 50 ms
     F_CPU=600000000	deg  C=30
    	50ms delay:: 50000 us and 50 ms
     F_CPU=24000000	deg  C=34
    	50ms delay:: 1050 us and 1 ms
     DONE 
     	 F_CPU=24000000	deg  C=31
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    void setup() {
      while ( !Serial);
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
    
      TimeDiff();
      set_arm_clock(240000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(110000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(24000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(600000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(130000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(110000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(24000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(600000000); // comment here to get full speed
      TimeDiff();
      set_arm_clock(24000000); // comment here to get full speed
      TimeDiff();
      Serial.printf("\n DONE \n \t F_CPU=%u", F_CPU_ACTUAL );
      Serial.printf( "\tdeg  C=%u\n" , (uint32_t)tempmonGetTemp() );
    #endif
    
    }
    
    static uint32_t t0;
    
    
    void loop() {
      // put your main code here, to run repeatedly:
    }
    
    void TimeDiff() {
    #if defined(__IMXRT1062__)
      Serial.printf("\n F_CPU=%u", F_CPU_ACTUAL );
      Serial.printf( "\tdeg  C=%u\n" , (uint32_t)tempmonGetTemp() );
    #endif
     while (!(millis()>(t0+1000)));
       t0=millis();
       uint32_t t1=micros(), t2=millis();
       delay(50);
       Serial.printf("\t50ms delay:: %u us and %u ms", micros()-t1, millis()-t2);
    }
    Last edited by defragster; 10-18-2019 at 07:37 PM.

  3. #3
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,367
    the following code
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    extern volatile uint32_t systick_cycle_count;
    
    uint32_t m_micros(void)
    {
      uint32_t ccdelta, usec, smc, scc;
    //  do {
    //    __LDREXW(&systick_safe_read);
        smc = systick_millis_count;
        scc = systick_cycle_count;
    //  } while ( __STREXW(1, &systick_safe_read));
      ccdelta = ARM_DWT_CYCCNT - scc;
      usec = 1000*smc + (ccdelta/(F_CPU_ACTUAL/1000000));
      return usec;
    }
    
    void setup() {
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
      set_arm_clock(24000000); // comment here to get full speed
    #endif
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
     static uint32_t t0;
     if(millis()>(t0+1000))
     {
       t0=millis();
       uint32_t t2=millis();
       uint32_t t1=m_micros();
       delay(50);
       Serial.printf("%d %d\n", millis()-t2, m_micros()-t1);
     }
    }
    gives me
    Code:
    49 50004
    49 50003
    1 1048
    1 1048
    49 50004
    1 1048
    49 50004
    1 1048
    49 50003
    1 1048
    49 50004
    1 1047
    49 50003
    1 1048
    1 1048
    1 1045
    49 50004
    1 1048
    49 50004
    1 1048
    1 1048
    1 1048
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    49 50004
    1 1048
    1 1047
    1 1048
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    49 50004
    1 1048
    49 50004
    1 1048
    1 1047
    1 1047
    1 1044
    1 1047
    1 1047
    1 1048
    1 1048
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    49 50004
    1 1048
    1 1048
    1 1048
    1 1047
    1 1047
    1 1047
    1 1047
    49 50004
    1 1048
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    1 1047
    that is, result is frequently correct

    but uncommenting the ARM code
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    #include "arm_math.h"  // micros() synchronization
    extern volatile uint32_t systick_millis_count;
    extern volatile uint32_t systick_cycle_count;
    extern uint32_t systick_safe_read;   // micros() synchronization
    
    uint32_t m_micros(void)
    {
      uint32_t ccdelta, usec, smc, scc;
      do {
        __LDREXW(&systick_safe_read);
        smc = systick_millis_count;
        scc = systick_cycle_count;
      } while ( __STREXW(1, &systick_safe_read));
      ccdelta = ARM_DWT_CYCCNT - scc;
      usec = 1000*smc + (ccdelta/(F_CPU_ACTUAL/1000000));
      return usec;
    }
    
    void setup() {
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
      set_arm_clock(24000000); // comment here to get full speed
    #endif
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
     static uint32_t t0;
     if(millis()>(t0+1000))
     {
       t0=millis();
       uint32_t t2=millis();
       uint32_t t1=m_micros();
       delay(50);
       Serial.printf("%d %d\n", millis()-t2, m_micros()-t1);
     }
    }
    gives consistently
    Code:
    1 1045
    1 1047
    1 1045
    1 1048
    1 1048
    1 1045
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048
    1 1048

  4. #4
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,367

    Solved?

    doubling the set_arm_clock command seems to work
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    void setup() {
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
      set_arm_clock(24000000); // comment here to get full speed
      set_arm_clock(24000000); // comment here to get full speed
    #endif
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
     static uint32_t t0;
     if(millis()>(t0+1000))
     {
       t0=millis();
       uint32_t t2=millis();
       uint32_t t1=micros();
       delay(50);
       Serial.printf("%d %d\n", millis()-t2, micros()-t1);
     }
    }
    produces
    Code:
    50 50005
    50 50005
    50 50005
    50 50005
    50 50005
    50 50005
    50 50005
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    50 50004
    conclusion: are there some wait missing in the set_arm_clock function?

  5. #5
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,220
    Since I was playing I tried various clock settings using just one setArmClock call. It seems to start going off below 200Mhz. At 180Mhz am seeing:
    Code:
    50 50001
    50 50000
    50 50000
    50 50000
    50 50001
    50 50001
    50 50001
    50 50001
    50 50001
    50 50001
    above that its right on. At 150Mhz you start seeing what you are seeing and just gets worse as you lower the clock. At 150Mhz
    Code:
    3 3007
    1 1007
    49 50000
    1 1007
    1 1007
    49 50000
    1 1007
    1 1007
    Even if I double up on the set clock calls at 150Mhz it is still off.

    Can't remember but 150Mhz sounds familiar for another clock as well Hmm

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,967
    Quote Originally Posted by mjs513 View Post
    Since I was playing I tried various clock settings using just one setArmClock call. It seems to start going off below 200Mhz. At 180Mhz am seeing:



    above that its right on. At 150Mhz you start seeing what you are seeing and just gets worse as you lower the clock. At 150Mhz

    Even if I double up on the set clock calls at 150Mhz it is still off.

    Can't remember but 150Mhz sounds familiar for another clock as well Hmm
    As @mjs513 notes - and I saw in p#2 code - : there is something off in the transitions with set_arm_clock - with orderly transitions some affect on millis() clock is resolved - on some others it is not.

    The '__LDREXW' code 'normally' only triggers if the millis_tick happens during the few cycles of the micros() code - i.e. in testing I ran it in tight loops to get EVERY microsecond change - that is multiple calls per us and only once per thousand micros() would the millis_tick happen even then.

    The problem is the millis() code even never calling micros() - a 50 ms delay only advances 1 millis() {that is the LEFT number} - which properly tells micros() only 1000 micros advanced in the 50 ms delay.
    1 1007
    49 50000
    Paul understands the clocks and knows of a specific interaction 'I Assume' from notes I've seen in the code when the PLL clock or whatever it was comes and goes during speed transitions that has to change to drive USB Serial or something.

    I did clock speed transition testing in Beta as I did micros() … but of course I did uniform steps of … down … up … which triggers what shows here where the one value/setting needing updated is caught.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,967
    Quote Originally Posted by WMXZ View Post
    doubling the set_arm_clock command seems to work
    Code:
    #if defined(__IMXRT1062__)
    extern "C" uint32_t set_arm_clock(uint32_t frequency);
    #endif
    
    void setup() {
      // put your setup code here, to run once:
    #if defined(__IMXRT1062__)
      set_arm_clock(24000000); // comment here to get full speed
      set_arm_clock(24000000); // comment here to get full speed
    #endif
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
     static uint32_t t0;
     if(millis()>(t0+1000))
     {
       t0=millis();
       uint32_t t2=millis();
       uint32_t t1=micros();
       delay(50);
       Serial.printf("%d %d\n", millis()-t2, micros()-t1);
     }
    }
    produces
    Code:
    50 50005
    50 50005
    50 50005
    ...
    conclusion: are there some wait missing in the set_arm_clock function?
    Re-reading this - it points to the problem and the conclusion seems an explanation in the right direction.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •