This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F149: Impossible C behavior

Part Number: MSP430F149


Tool/software:

Why won't main() jump to l_delay()? Note the while(1) put in the l_delay() sub routine. That should crash the program. But the main loop still  runs at 65khz no matter what is done to l_delay().

This does run as expected on an Atmel processor (with their port and bit labels) using the ICC compiler. And I have been using crude delay routines like this for years.

#define bit_tst(A,B) (A & B)
#define bit_set(A,B) A |= B
#define bit_clr(A,B) A &= ~B
#define bit_tog(A,B) A ^= B

#include <msp430f149.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "ILI9163lcd.c"

// button ports
#define BUTN_ENTER      !P6IN,BIT0
#define BUTN_UP         !P6IN,BIT1
#define BUTN_DOWN       !P6IN,BIT2
#define BUTN_LEFT       !P6IN,BIT3
#define BUTN_RIGHT      !P6IN,BIT4

#define RUN_LED_ON()    bit_set(P2OUT,BIT7)
#define RUN_LED_OFF()   bit_clr(P2OUT,BIT7)

static init_ports(void)
{
    P1DIR = 0xFF;
    P2DIR = 0xFF;
    P6DIR = 0x0;
    P1OUT = 0x0;
    P2OUT = 0x0;
    P6OUT = 0x1F;  // pull ups
}

void l_delay(int d)
{
   int a,b;
while(1);
    for (a = 0; a < d; a++)
         for (b = 0; b < d; b++);
}

int main()
{
	WDTCTL = (WDTPW | WDTHOLD);  // stop watchdog timer
    init_ports();
//  init_uart();
	RUN_LED_OFF();
//	ILI9163_init(0);
	RUN_LED_ON();
	
	while(1)
	{
	    l_delay(1000);
	    RUN_LED_OFF();
	    l_delay(1000);
	    RUN_LED_ON();
	}

}

  • Hello Andy,

    Maybe this is being optimized out by the compiler?  I'm not familiar with an ICC compiler, but it's possible it's being removed.  In your debugger, can you look at the disassembly and see what it's actually putting there?  

    For MSP430, we usually use " __delay_cycles(10000);" to implement very basic delays.  

    Thanks,

    JD

  • Well not trying to be funny here, but what gives the compiler the right to blindly delete code without human permission? I'll check out the disassembler.

    Coming from 20 years of Atmel and ICC_AVR, I'm not impressed so far with CCS.

    As for the __delay_cycles(10000), ICC_AVR has a similar delay library function. But here can I find a listing for these extended functions in CCS?

    Note it does throw up these two remarks:

    "../main.c", line 38: remark #1527-D: (ULP 2.1) Detected SW delay loop using empty loop. Recommend using a timer module instead
    "../main.c", line 39: remark #1544-D: (ULP 13.1) Detected loop counting up. Recommend loops count down as detecting zeros is easier

    But still, my for loops are perfectly legal C expressions and have years of proven functionality for me.

  • Hey Andy,

    Luckily the compiler keeps us from having to write assembly but unfortunately, it gets to decided how to implement our c-code in that assembly.  

    You can turn down the compiler optimization settings in the project settings, here:

    If you turn it down to 0, it will try to do the most literal interpretation possible.  

    Hope this helps and have a good weekend,

    JD

  • Well JD, you were right! Running in Debug mode, it does skip right over the l_delay() call like it's not even there. WTH? 

  • Well not trying to be funny here, but what gives the compiler the right to blindly delete code without human permission? I'll check out the disassembler.

    Good C compilers have been doing this (dead code removal) for years. The compiler analyses the code, sees that it does nothing which effects anything else, then removes it. Making things faster is the point so it doesn't care about your intended delay.

    As for delay_cycles, it isn't a function but results in the compiler generating the required code. Really simple for __delay_cycles(1) but more complicated for longer delays.

  • "Luckily the compiler keeps us from having to write assembly but unfortunately, it gets to decided how to implement our c-code in that assembly. "

    Yes I know optimizers can create issues but I never heard of one deleting code like this? It's not an "empty loop" as the compiler reports. It's a delay routine not much different than pages of NOP back in the PDP-11 days to get millisecond timing!

  • OK Dave, but where can I find the library(s) listings for these CCS specific functions? I won't find  __delay_cycles(1) in the K&R C bible.

    I have no issue using  __delay_cycles(1), in fact this is just to test the hardware here. But what concerns me now is what else the compiler may be changing that I don't know about. Generate an optimizing report with suggestions, but don't just blindly modify code flow like this. Allow the developer to judge and test optimizing improvements.

  • The __delay_cycles(x) works. But it's not accurate. With my technique which CCS disallows, I can tweak the inner loop to get precise timing where 100 is actually 100ms.

    Use one of the hardware timers? Yes I do that for very precise timing, But that eats up an interrupt time slot which may prove critical. The tweakable delay method is most often close enough when outside of a critical loop, closer than the __delay_cycles().

  • There is no library listing as the compiler generates the code on the fly. It may need a loop or maybe not.

  • The keyword "volatile" can be used to get the compiler to leave your code alone. There was a thread on this here recently...

    e2e.ti.com/.../msp430fr5969-question-about-the-use-of-volatile-in-the-blink-the-led-example

  • Misunderstanding? You and JD both proposed using __delay_cycles(), which is great. But how did you know that function exists? My K&R C bible example is the authentic listings of the C language. If I want to know what printf() does I can look it up there.

    More questions for __delay_cycles() - is the value passed a uint8, uint16, int16, int32? What does it return if anything? Where is the documentation of this function? 

    So where do I find a listing of these non-standard compiler specific functions in CCS? I'm sure there are more that are quite useful.

  • The CCS compiler guide references the IAR guide for intrinsic functions like __delay_cycles().

**Attention** This is a public forum