5
\$\begingroup\$

After enabling a clock for a certain port you have to wait 4 cycles for the clock to finish initializing. How can one wait for N cycles the proper way?

In my code I used this:

__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");

After which uKeil IDE seem to stop complaining.

\$\endgroup\$
4
  • 3
    \$\begingroup\$ Alternatively you wait loop on the clock status register. In case it takes longer to initialize than expected (pll fault or power on brownout/crystal startup) \$\endgroup\$
    – crasic
    Commented Mar 14, 2016 at 3:10
  • 1
    \$\begingroup\$ NOPs are bad idea. "NOP does nothing. NOP is not necessarily a time-consuming NOP. The processor might remove it from the pipeline before it reaches the execution stage. Use NOP for padding, for example to place the following instruction on a 64-bit boundary." which is quoted from infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/… \$\endgroup\$
    – Ayhan
    Commented Mar 14, 2016 at 11:01
  • 1
    \$\begingroup\$ these mcus are pipeline based and not deterministic, so unlike the old days you cant just insert instructions and assume they take some amount of time. you can tune some code in a certain situation sure, but you have to tune it you cant just count instructions. The correct way to consume a specific amount of time is to use a timer (and then there is the non-deterministic latency and handler code that goes with it but it is more predictable and reliable than hand counting instructions). \$\endgroup\$
    – old_timer
    Commented Mar 14, 2016 at 17:11
  • \$\begingroup\$ if you just want to kill some time in a simple way and not have the compiler get in your way, voltatile works, I prefer a dummy function, in some asm place the instruction bx lr. then make a loop for(i=0;i<100;i++) dummy(i); and the compiler cannot optimize that loop away. \$\endgroup\$
    – old_timer
    Commented Mar 14, 2016 at 17:13

1 Answer 1

2
\$\begingroup\$

This is one method from here:

 volatile unsigned long delay;

 SYSCTL_RCGC2_R |= 0x00000010;   // 1) activate clock for Port E
 delay = SYSCTL_RCGC2_R;         //    allow time for clock to stabilize

You could also set up us the clock(s) and go do something else for a few cycles (initialize some stuff) but that's a potential bug in the future.


Edit: The dummy line compiles to:

  400286:   681b        ldr r3, [r3, #0]
  400288:   9301        str r3, [sp, #4]

On the Cortex M4

ldr is 2 cycles

str is 2 cycles

See here for M4 cycle counts.

The volatile keyword keeps the ldr and str instructions from being combined, as I understand it.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I see what you did there. \$\endgroup\$
    – gbarry
    Commented Mar 14, 2016 at 3:28
  • 1
    \$\begingroup\$ I've seen this before, but it's very vague to me. How do I know if a dummy assignment will take at least 4 cycles? \$\endgroup\$
    – Darkhan
    Commented Mar 14, 2016 at 6:40
  • \$\begingroup\$ @Daveel ; I think "memory barriers" and "volatile" will give you the answer \$\endgroup\$
    – user16324
    Commented Mar 14, 2016 at 12:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.