# How does __delay_cycles work?

I'm using a msp430g2553 and setting the clock to 1Mhz:

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;


I've timed a 5 million cycles and it unexpectedly takes around 6 seconds (I was expecting 5). The loop I've used is:

int i;
for(i=0;i<5000;i++)
__delay_cycles(1000);


I've read about using interrupts (probably based on Timer_A, etc) but I'd like to avoid that for now.

So my question is: how can I implement a constant argument sleep based on __delay_cycles?

Later edit

Assembly for:

void delay1000() {
__delay_cycles(1000);
}


is:

delay1000:
0c3b4: 04 12                     PUSH    R4
0c3b6: 04 41                     MOV     SP,      R4
0c3b8: 24 53                     INCD    R4
0c3ba: 3f 40 4c 01               MOV     #0x014c, R15    // 332 decimal (1000/3 -> DEC, TST and JNZ)
0c3be: 1f 83                     DEC     R15
0c3c0: 0f 93                     TST     R15
0c3c2: fd 23                     JNZ     delay1000+0xa
0c3c4: 03 43                     NOP
0c3c6: 03 43                     NOP
0c3c8: 34 41                     POP     R4
0c3ca: 30 41                     RET

-

Look at the dissassembly of the code, remember the for loop adds some instructions which take a few cycles. With a 5000 loop, these extra cycles will add up. Also, how delay_cycles() is implemented can make a big difference.
You can count the cycles for each loop in the simulator, do the math and compensate for the added cycles by passing the appropriate value.

Of course, the best way to get accurate timing is to use interrupts, but you say you want to avoid those for now.

-
I don't know about this particular microcontroller, but a loop like this potentially breaks the CPU's pipelining, resulting in a relatively large timing error. –  jippie Jan 3 '13 at 14:03
That depends on the contents of __delay_1000, which we don't know. As far as the outer loop is concerned, there isn't much pipelining to worry about in an MSP430. –  Brian Drummond Jan 3 '13 at 14:20
I didn't expect a simple loop comparison to account for such a difference but after looking at how __delay_cycles is implemented it makes sense. Thanks for the answer. –  diciu Jan 3 '13 at 14:33
@diciu - Yes, you're right, such a large difference won't all be due to the added instructions - these delay routines are difficult to write to accommodate a very large range timescale-wise, so they often lose accuracy at the extreme ends of the scale. As long as you can look at the implementation/disassembly though, you can adjust things to make sure your code works as intended. –  Oli Glaser Jan 3 '13 at 14:58

From the MSP430 Optimizing C/C++ Compiler v 3.1 User's Guide (SLAU132c.pdf) pp. 109:

The __delay_cycles intrinsic inserts code to consume precisely the number of specified cycles with no side effects. The number of cycles delayed must be a compile-time constant.

It is a intrinsic function, specifically designed to use up cycles. It should be good for at least that number of cycles. You can change 1000 to something else (it must be a constant, can't be a variable). Both the for loop and the function call will add to the delay.