Let’s go back to looking the First Project we created and ran in Chapter 2.
Just like any C application running on a personal computer, main() is the entry point of the user application.In the code above, the first line executes something that a programmer on an x86 machine has never seen. WDTCTL could be a variable, but where is it defined? What are DDTPW + WDTHOLD? The answers comes down to the fact that microcontrolles require much low level configuration.
All computers are based on the idea of having a CPU operate on registers. Registers are memory locations that the CPU uses to store and load data. Microcontrollers take this concept further. They integrate a variety of peripherals which are modules external to the processor itself. Clocks, Timers, Communications modules, Analog to Digital converters are all external peripherals (as seen by the CPU). But, the CPU can access them via memory mapped registers. These registers are bit locations that control the peripherals and exchange information with them. In the code above, WDTCTL is the Watchdog Timer control register. The watchdog timer is an external peripheral who’s job is to reset the system when something in the code has gone wrong and the CPU is hung. Note that WDTCTL is just the name of the register. Texas Instruments has already defined WDTCTL with the right memory location where it is present. WDTCTL is very much a preprocessor define and we don’t have to worry about the actual address. Using this define makes the code much more readable. After all, would you immediately know what the register does at 0x800 or if you saw WDTCTL?
The key to accessing WDTCTL and the rest of the registers is the inclusion of MSP430.h. This header file should be included in almost every C source file. This file is actually full of its own includes with #ifdef that makes the compiler automatically include the header for the right MSP430 in use (given that the right one has been selected when creating the project). Another important thing to note is that we are operating on the register by assigning to it using the equals sign. WDTPW and WDTHOLD are bit definitions that also come by way of msp430.h and they allow us to set the password of the watchdog timer and stop it. We won’t delve into the intricacies of the Watchdog timer at the moment, but we need to know that for safety reasons, the watchdog timer is always automatically started when the CPU begins. Because our code is simplistic and doesn’t “pet” the watchdog timer. we need to disable it or the MSP430 will get restarted continually.
The line following the watchdog control controls P1DIR. This register is also defined in the headers and controls the direction of the pins in Port 1. Note that we set bit 0 high, while leaving all the other bits as-is.
The code then loops forever, toggling P1OUT which controls the value of pin P1.0 (Port 1 bit 0). We have included a for loop to delay the toggling of the Pin so we can visibly see the change in the LED on and Off.
Coming from Restart
You might think that the MSP430 starts and jumps straight to main, but this is not true for programs using C. In reality, there is a lot happening behind the scenes when the MSP430 comes out of reset (either due to power on or a reset due to exception).
After a reset, the system goes to a default state:
- RST/NMI pin is configured in reset mode
- I/O pins are in input mode (High Impedance), making them have no effect on the circuit they are in
- Peripherals are initialized as described in their user guide chapter
- Status Register is in Reset
- Watchdog timer is active in Watchdog Mode
When a reset happens, along with the list above, the MSP430’s CPU is automatically loading with the address of either:
- Reset Vector
- Bootstrap Loader Code Address
For devices that don’t have any Bootstrap Loader (BSL) in either ROM or Flash, the CPU is loaded with the Reset Vector.
The BSL is code stored in the MSP430 by TI during manufacturing that allows you to upload code to the MSP430 via UART or other interfaces (such as USB for devices that include USB support). By running at the start before any user code, we can download code. We won’t cover the details of the BSL itself, but there are several documents from TI describing the mechanism of of accessing the BSL and downloading code. The BSL itself configures the MSP430 with a minimum of configuration needed to support UART.
Whether we arrive at Reset Vector from BSL or directly, doesn’t much matter.
The reset vector is located at 0FFFEh, meaning the Program Counter register of the MSP430 CPU will be loaded with this value and the CPU will begin executing the instructions starting at this address. The code needs to do the following
- Initialize the Stack Pointer (SP) Register. This is usually set to the top of RAM but depending on the linker configuration can be set differently.
- Initialize the Watchdog timer, disable it or configure it for periodic system checks
But we never saw this code for the Stack Pointer anywhere! And we sure never dealt with the Reset Vector!
The answer here is that C compiler takes care of this for us. The C compiler includes routines that run after start that go even further:
- All variables in memory that need initialization are initialized to their value during this time
All these issues are something one never deals with in a desktop computer, unless you write BIOS for a living.
At main, your task is to configure the MSP430 for your application. The MSP430 is minimally ready, with a basic clock running to allow instructions to execute, but in most cases everything is in the reset state. Some of the things the User Application needs to do includes:
- Configure the Clocks in the system according to what is needed and according to the clock sources available
- Configure the Pin Muxing for GPIO and Modules
- Configure Peripherals such as UART, SPI, etc
The code above uses a for loop to create a time delay. This is something we would never do when programming on an x86 processors, but the MSP430 is a microcontroller with clocks running at relatively slow speeds compared to an Intel processor. The MSP430 can run up to 25MHz, although the MSP430G2553 itself can go only up to 16MHz. At 16MHz every cycle is 62.5ns. 20000 cycles result in a 1.25ms. On a personal computer, we rarely concern ourselves with the clock speed unless we’re selecting between processors. But, in microcontrollers, clock frequency affects almost every aspect of the device’s operation, from whether it can handle processing a certain amount of data to the baud rate of the UART interface.
The MSP430 clock system has an entire chapter devoted to understanding it, but it’s important to know that the MSP430 as it is configured by the code above runs with the default internal digital oscillator clock. This clock is started by default and runs the main CPU. After startup, the DCO is configured for RSELx = 7 and DCOx = 3 which means it is running at around 1.2MHz, depending on temperature and other factors. So the 20000 or so cycles actually slow down the LED much more. Note that the for loop does not translate to 20000 clock cycles given that the loop must perform a few operations including decrementing and a comparison which can take a few cycles in and of themselves.
Sign up to get updates and more
MSP430 Tutorial Chapters
- Preface and Introduction
- Chapter 1 – MSP430 Development Hardware
- Chapter 2 – Getting Started with the MSP430
- Chapter 3 – Number Systems and Operations
- Chapter 4 – Deeper Dive into Using the MSP430
- Chapter 5 – General Purpose Input Output (GPIO)
- Chapter 6 – MSP430 Clocks
- Chapter 7 – MSP430 Interrupts and Low Power
- Chapter 8 – MSP430 UART Peripheral
- Chapter 9 – MSP430 Serial Peripheral Interface (SPI)