ESE101: C is for Cookie, and also C

Welcome back!

The Intro

Last time we generated a simple blinky example program in C using TI’s Code Composer Studio (CCS). Go back to the previous post if you need a reminder of how we did it.

In this post, I’ll introduce the C programming language by walking through the blink.c C code that CCS created for us. C source code files typically end in .c. They don’t have to, the file name doesn’t matter, but it’s helpful to follow that convention.

The Code

Here’s blink.c with the line number at the start of each line. I’m just putting it here for reference so you refer to the whole program at once if that’s helpful to you.

    1    #include <msp430.h>
    4    /**
    5     * blink.c
    6     */
    7    void main(void)
    8    {
    9        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    10       P1DIR |= 0x01;              // configure P1.0 as output
    12       volatile unsigned int i;    // volatile to prevent optimization
    14       while(1)
    15       {
    16           P1OUT ^= 0x01;          // toggle P1.0
    17           for(i=10000; i>0; i--); // delay
    18       }
    19   }

Let’s start at the top of the file and work our way down. I’ll try to explain what each line is doing, but we’ll ignore some details for now until later posts. Don’t get hung up on anything that isn’t clear after reading this. Absorb what you can from one or two readings, and I promise that it will become clearer as you read and write more C code.

The Explanation

Line 1:

    #include <msp430.h>

This line tells the compiler to copy the file msp430.h inside this file (blink.c). The file msp430.h is called a header file. A header file contains C code that defines helpful things that can be used by other files; often it contains information that many other components need. In this case, the msp430.h header file contains definitions for MSP430 peripheral memory addresses and a bunch of other helpful definitions that most C programs running on an MSP430 will need.

Lines 4-6:

     * blink.c

These three lines are comments, meaning the compiler will completely ignore them. These are notes to ourselves - and more importantly to our colleagues and our future selves! There are two forms of C comments. The original C comment style is shown here in lines 4-6: a comment is everything between /* and */. Note that any extra stars in a comment are there only because the programmer think it looks better; they are not required.

The newer C comment style was borrowed from C++: a comment is everything after //, until the end of a line. We’ll see // comments later in the code.

Lines 7-8 and line 19:

    void main(void)
        … many other lines, ignore them for now …

I’ve included line 19 in with lines 7 and 8 because they go together.

Line 7 declares a function called main. A function is a collection of C code that is run or called as a unit. Every C program starts running in a function called main, and every C program must have a main function.

A function must have a name, a return type, and zero or more arguments. Arguments are also called function parameters. As you might have guessed from line 7, a function declaration looks like this:

    function_return_type function_name (function_arguments)
      … The function consists of everything inside the curly braces …

So in line 7:

  • The first void is the return type: this means the function does not return a value.

  • main is the function name.

  • The second void is the function’s argument. This means the function does not take any arguments.

Everything between the open curly brace { on line 8 and the closing curly brace } on line 19 is the function body. The function body is run when the function is called.

Line 9:

    WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer

This line sets a variable called WDTCTL equal to the bitwise OR of two values. The “|” symbol is the symbol for the bitwise OR operation; the vertical line symbol “|” is also called a pipe. See Andrei Chichak’s Embedded Wednesdays post on bitwise operators for more information.

WDTCTL is set to the value of WDTPW bitwise OR’d with the value of WDTHOLD. The comment “// stop watchdog timer” tells us that the programmer wants this line of code to stop the watchdog timer. Believe it or not, this comment is very helpful! The WDTPW and WDTHOLD symbols are not self-explanatory; even after reading the MSP430 reference manual I bet I would forget what those symbols mean a few days after using them. This comment is the only way I’d have a hope to understand what this code was doing without diving back into the MSP430 reference manual.

Line 10:

    P1DIR |= 0x01;  // configure P1.0 as output

This does something similar to line 9 with the bitwise OR assignment operator. Here the P1DIR variable is set using the “|=” operator, which means the same thing as:

    P1DIR = P1DIR | 0x01;

So this sets bit 0 of P1DIR to 1, and leaves the other bits in P1DIR unchanged. If bit 0 was already 1, then it stays 1.

Line 12:

    volatile unsigned int i; // volatile to prevent optimization

This declares a variable. Declaring a variable in C tells the compiler “I want a variable of a certain type and I’ll give it a name.” In this case, the variable’s type is volatile unsigned int, and the variable’s name is i. For now it’s good enough to understand that the variable i can hold integer numbers. The keyword volatile is a big topic for another post (or many posts…).

Lines 14-15 and line 18:

      … ignore the lines inside the while loop for now …

Line 14 is the start of a while loop. A while loop is the C keyword while followed by a conditional statement inside parentheses, and then the body of the loop.

A while loop runs the code inside of its body for as long as the conditional statement is true. A conditional statement is C code that evaluates to either true or false. A simple example of a conditional statement is:

    age < 40

This conditional statement is true if the variable age is less than 40, else it’s false.

Our blink.c line 14’s conditional statement is simply the number 1 inside the while’s parentheses. In C, any non-zero number is considered true when it’s used as a conditional, so this while loop is always true, and will run forever. This is also called an infinite loop because the loop will run an infinite number of times.

Let’s look at the whole while loop now, from line 14 to 18:

         P1OUT ^= 0x01;           // toggle P1.0
         for(i=10000; i>0; i--);  // delay

A while loop’s body is the code inside the curly braces { and }. Lines 16 and 17 are the body of this while loop.

Line 16:

    P1OUT ^= 0x01; // toggle P1.0

This assigns the P1OUT variable using the bitwise XOR assignment operator. This is identical to this C code:

    P1OUT = P1OUT ^ 0x01;

As the comment says, this toggles bit 0 of the P1OUT variable. Again, please see Andrei’s post about bitwise operations for more info about what an XOR is.

Line 17:

    for(i=10000; i>0; i--); // delay

This is a for loop. A for loop is similar to a while loop: it’s the word for followed by a bit of code inside parentheses. The stuff inside a for loop’s parentheses tells the for loop how many times to run the body of the for loop, similar to a while loop.

Don’t worry about the particulars for now: just understand that this for loop sets the variable i = 10000, and then “i--” subtracts 1 from i. The for loop continues as long as i > 0. Then the for loop is done and the program moves on to the next line. In this case, the next line is actually line 16 because the while(1) loop causes us to run lines 16+17 forever.

The Point

The point of this post was to give you a quick look at some C code. Hopefully the blink.c file makes more sense to you than it did when you started reading it, but you may not understand everything about what the code is doing...

The Cliffhanger

...until next time! Okay, next time you still may not understand everything, but you’ll understand more.

Next time we’ll step through the C code in CCS’s debugger and see how the C code corresponds to the assembly code that actually runs on the MSP430 chip.

Footnote: Please note that TI’s comment “// volatile to prevent optimization” is misleading and incorrect. Many programmers think that volatile tells the compiler to not optimize a variable; this is subtly wrong! Comments are written by people for other people to read, and sometimes the people are wrong, sometimes the comments are wrong, and sometimes both are wrong!

Sugar cookie with pink frosting and rainbow sprinkles on holiday tablecloth, mixed media, 2018

Sugar cookie with pink frosting and rainbow sprinkles on holiday tablecloth, mixed media, 2018