Summary: This is a basic tutorial on how to program the basic digital peripherals on the ez430.
Configuring Digital I/O: Introduction
Digital I/O, such as the LED, is configured by modifying several registers pertaining to the port that they are attached to. Check the datasheet to find the respective port number of the peripheral you which to control. For more detailed information about Digital I/O on the MSP430 check Chapter 6: Digital I/O of the ez430's user guide. The basic logic behind seemingly trivial process of turning the LED on and off is the same behind the operation of every peripherial on the tool.
First, we must assign the direction of the corresponding I/O pins. This is done by setting the direction register, PxDIR, with the appropriate bit. By default, all I/O pins are assigned to be inputs.
- Bit = 0: The port pin is switched to input direction.
- Bit = 1: The port pin is switched to output direction.
On the ez430 the LED is located on port 1. The port number will correspond the to x value in registers such as PxIN, PxOUT, orPxDIR. Therefore, if we wanted to define the direction of a pin on port 1 we would write to P1DIR.
A Useful Tangent: Common Bitwise C Operations
In order to modify values of registers you must first understand the following commonly used C logic operations:
~A
A | B
A & B
A ^ B
A |= B
A &= ~B
A ^=B
In C, the NOT:
~
, OR: |
, AND: &
and XOR: ^
operators are all bitwise. This means that the operations are done bit by bit to the binary values of the two operands.NOTE:
The prefix "0b" to a number means that that number is binary. Similarly an "0x" prefix means that the number is hexadecimal.
int A = 0b1101;
int B = 0b0101;
int C;
/*
The results of these operations are very straightforward. If we are dealing with the "|"
operator then we OR together each bit to make the result. This means 0b1101 | 0b0101 is
computed as [1 OR 0, 1 OR 1, 0 OR 0, 1 OR 1] which is [1,1,1,1] thus the result is 0b1101;
*/
C = ~A; // The value of C is 0b0010
C = A | B; // The value of C is 0b1101
C = A & B; // The value of C is 0b0101
C = A ^ B; // The value of C is 0b1000
C and Macros with Texas Instruments' ez430
Summary: Programming basic C on an embedded processor.
The primary difference between "normal" and embedded C programming is that you will need to write directly to registers to control the operation of the processor. Fortunately, the groundwork has already been laid for you to make this easier. All of the registers in the ez430 have been mapped to macros by Texas Instruments. Additionally, the important bit combinations for each of these registers have macros that use the same naming convention as the user’s guide. Other differences from the C used on most platforms include:
- Most registers in the ez430 are 16 bits long, so an
int
value is 2 bytes (16 bits) long.- Writing to registers is not always like writing to a variable because the register may change without your specific orders. It is always important to read the register description to see what the register does.
- The watchdog timer will automatically reset the ez430 unless you set the register not to.
- There is only a limited "standard out" system. Standard out will typically print results to your computer screen.
- Floating-point operations cannot be efficiently performed. In general, you should avoid floating point decimal calculations on the ez430 because it does not have special hardware to support the complicated algorithms used.
EXERCISE 1
Code Review
In this exercise, you may want to use some of the debugging tools (Breakpoints, Watch Window, Locals Window) to help you understand what the code is doing. Start a new project. Cut and paste the following code into main.c:#include "msp430x20x3.h" void main(void){ int i,j,tmp; int a[20]={0x000C,0x0C62,0x0180,0x0D4A,0x00F0,0x0CCF,0x0C35,0x096E,0x02E4, 0x0BDB,0x0788,0x0AD7,0x0AC9,0x0D06,0x00EB,0x05CC,0x0AE3,0x05B7,0x001D,0x0000}; for (i=0; i<19; i++){ for (j=0; j<9-i; j++){ if (a[j+1] < a[j]) { tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } } while(1); }
- Explain what this program is doing. Why is the
while(1)
statement at the end of the code necessary for all programs we write at this point?- Use any of the methods listed above to show the updated array. What is the final result?
- Modify the code so that it prints the final version of the array to standard out (you will have to use a loop of your choice to cycle through each element of the array). What are the drawbacks and benefits of using
printf
over setting a breakpoint?HINT:
To use the standard out, add the following line to the top of your code:Then, select Project->Options, the Library Options tab in General Options, and finally select Tiny in thePrintf formatter drop down menu. The#include "stdio.h";
printf()
function will print to standard out (when the debugger is running, select View->Terminal I/O). For example,printf("x equals %d\n", x);
will print out the value of x to the window. The%d
means that x is a number, and\n
will produce a line break.EXERCISE 2
Functions
Multiplications and division are very complex operations to do on any microprocessor. The operations should be avoided if possible or should be replaced with simpler, equivalent operations.
- What do the operators << and >> do?
- How could you use these operators to perform multiplication and division?
- Write the function
multiply(int x, int y)
that takes parameterx
and multiplies it byy
by using a bit shift. It must return anint
. For symplicity, it is OK to assume thaty
is a power of 2.- Next, write the function
divide(int x, int y)
that takes parameterx
and divides it byy
by using a bit shift. It must also return anint
.EXERCISE 3
Digital I/O Registers
Open the header file msp430x20x3.h by right clicking the name in your code and selecting Open "msp430x20x3.h" This file contains the macros and register definitions for the ez430 we are using. Using the ez430 schematic, this header file, and ez430's User Guide please answer the following questions.
- The Watchdog Timer will automatically reset the hardware if it isn't periodically reset or disabled entirely. Usually, we will simply disable it. It can be disabled by writing to the
WDTPW
(watchdog timer password) andWDTHOLD
(watchdog timer hold) section of the Watchdog Timer Control Register (WDTCTL
). Refer to Section 7.3 of the User's Guide for more information. Find the macros for this register in the header file. How are they different from their description in the User's Guide? Finally, write the C code required to disable it.- What are the differences among P1DIR, P1SEL, P1OUT, P1IN?
- Some port pins have multiple functions to output and it is up to the user to select the appropriate signal. Write some code that would select the alternate function of P2.2 (pin 2 of port 2). What will the result be on our hardware?
EXERCISE 4
Programming Digital I/O
Write a program to blink SOS in Morse code repeatedly. In Morse code SOS is S:"..." O:"---" S:"..." where each '.' is a shorter blink and a '-' is a longer blink. According to The International Morse Code Standard (on Wikipedia) the relative lengths of times between dots and dashes are as follows:Make the delays (time length of a dot) by using a for-loop that counts to a large enough value.
- The amount of time of a dash is equivalent in length to 3 dots.
- The amount of time between parts of a letter is equivalent in length to one dot.
- The amount of time between letters is equivalent in length to 3 dots.
- The amount of time between words (assume each SOS is a word) is equivalent to 5 dots.
HINT:
Make sure you disable the watchdog timer at the very beginning of the program.
Operators such as
+=
or -=
, implemented as A += B
, are short forms for A = A + B
. This is translated to "take the current value of A, add it to B, and finally store that result back into A." For -=
it similarly translates to "subtract B from A and store the result back to A." If "@" is some operator, than A @= B
would be "@ together A and B and store the result back into variable A."If we combine the use of these two aspects of C then the aformentioned logic operations that are listed at the top of this section begin to make sense. The following examples will help you figure out why they are useful to us when we attempt to configure any register on our microcontroller. It is imperative that you understand how these function. You will use them in every program you write because these operations allow you to modify single bits of a register to modify a specific register and change a peripheral's settings.
Configuring Digital I/O: Examples
EXERCISE 1
How do we switch the pin (P1.0) corresponding to the LED to be an output?
Output pins may be toggled using the PxOUT register. The LED is turned on by setting its corresponding register bit high.
EXERCISE 2
What code would turn on the LED without modifying any other bits in the register? What would turn it back off?
EXERCISE 3
What would be the proper syntax for toggling the value of P1.0 so that we can turn the light on if it is off or vice versa?
EXERCISE 4
Now, write the full C program to turn on the LED. Do the following:
- Create a new project in Workbench as previosuly described
- Do not delete the default code in the main.c file except for the
return 0;
, which is not necessary. All of your programs will use this as a skeleton - Include the correct header file by adding the following line at the top of the main.c file:
#include "msp430x20x3.h";
- Consider defining macros for commonly used register values. For example, if we add
#define led_on ~0x01
to the top of the file (after the#include
) we may callled_on
every time we wanted the value ~0x01. Similarly we may add#define led_off 0x01
to use when we wanted 0x01. - Complete the program. It is as simple as it seems; no more than two lines of code in the main function are necessary
Software Setup and Introductory Assembly programs for the MSP430
Summary: This is Lab 3 of the Colorado State University Microprocessors course using the eZ430-F2012 development tool. This introductory lab will walk you through the process of creating an assembly project, assembling a program, downloading it to the EZ430 (the development kit for the TI-MSP430F2012) and executing / debugging the program. When you complete this lab, you should be able to: - Understand the IAR Embedded Workbench IDE. - Assemble (build) a program using the IAR Embedded Workbench. - Download a program onto your EZ430. - Run a program and examine memory registers. - Use stepping and breakpoints to debug the program. Because you will perform all of these procedures in every lab you do after this, a complete understanding of the material in this lab is necessary.
3.1 - Objectives
This introductory lab will walk you through the process of creating an assembly project, assembling a program, downloading it to the EZ430 (the development kit for the TI-MSP430F2012) and executing / debugging the program. When you complete this lab, you should be able to:- Understand the IAR Embedded Workbench IDE.
- Assemble (build) a program using the IAR Embedded Workbench.
- Download a program onto your EZ430.
- Run a program and examine memory registers.
- Use stepping and breakpoints to debug the program.
Because you will perform all of these procedures in every lab you do after this, a complete understanding of the material in this lab is necessary.3.2 - Reading Material
You will need to read the following introduction material prior to completing this lab, all are available on the ECE 251 website.- Introduction to the MSP430-F2012 controller
- Introduction to assembly programming
- MSP430 Instruction Reference Sheet
3.3 - Hardware / Software Setup
The eZ430 debugger/emulator should install its drivers automatically. To install IAR Embedded Workbench Kickstart Version, please visit www.ti.com or www.iar.com for the latest version of the software with installation instructions.3.4 - Introduction to IAR Embedded Workbench IDE
Invoke the IAR Embedded Workbench in one of the following two ways:- Left click your mouse on the START menu on the bottom left of your screen. Then follow the path, Programs -> IAR Systems -> IAR Embedded Workbench Kickstart for MSP430 V4.1-> IAR Embedded Workbench.
- Open Windows explorer and locate IAR Embedded Workbench.exe in the folder C:\Program Files\IAR Systems\Embedded Workbench 4.1\common\bin\IarIdePm.exe
To create the shortcut on your desktop, right click the mouse on IarIdePm.exe and then left click on create shortcut. Then click on this shortcut to invoke the IAR Embedded Workbench application.Step 1 – Creating a Project
The first thing you will see is the Embedded Workbench Startup screen. This screen will be a good shortcut to open existing workspaces and create new projects in the future, but for now, click the Cancel button. Note that a workspacecan hold one or more projects, each which can hold groups of source files (the files that contain your assembly code).Click on File -> New -> Workspace. This opens a new workspace in which to place your projects. You must always open a workspace before you can create a new project. To create a new project, click Project -> Create New Project… TheCreate New Project box will appear. IAR lets you choose whether you want to create an assembly (asm), C, or C++ project. Expand the asm tab and click OK once you have selected the asm option.Figure 1
New Project Window
IAR will ask you to specify where you would like to save your .ewp project file. It is recommended you create a folder for your workspaces on your u: drive such as u:\ee251\Labs\ in which you can store all your future labs. Create a folder calledLab 3, name your project Lab 3, and click Save. At this point, you should also download the add_primes.s43 file provided on the class webpage into the same folder.Look at the left of your screen. You will see the workspace window where your projects and source files are organized.Figure 2
Workspace Window
On the right is the project window. The project window shows the assembly file template discussed in Introduction To Assembly Programming from the pre-lab material. You will not be using this file for this tutorial. Before anything else, click on File -> Save Workspace and save your workspace in the same folder as the project.Now add the file we are going to examine in the tutorial. In your workspace window, right click on the project name and select Add -> Add Files… At the bottom of the page, change the Files of type tab to the Assembler Files option. If you downloaded the file from the class webpage, go ahead and select the add_primes.s43 file and click Open. You should see the file added to your workspace window. Right click on the asm.s43 template and remove it from the project then take a look at the add_primes.s43 code. This assembly program has stored the first six prime numbers in an array in memory and adds them up into register six. See if you understand what is going on by referencing the pre-lab material.Step 2 – Setting the Project Options
Before we can compile our code into an executable object file, we need to set the project options. Using the Project pull-down menu select Options or simply right click on the project and select Options… This will bring you to the Options for node “<project_name>” screen.Figure 3
Project Options Screen
- In the General Options menu:
- Set the Device to the MSP430F2012 or whatever MSP430 device number you are using.
- In the Debugger menu:
- Set the Driver to FET Debugger. This makes sure that once compiled into an object file, the program will be loaded onto your physical microcontroller, not the IAR simulator.
- If you would ever like to work on your code but you do not have your EZ430, you can set the Driver option to Simulator and the IAR Embedded Workbench will simulate your microcontroller.
- Under the actual FET Debugger menu:
- Change the Connection from LPT -> LPT1 to TI USB FET. This tells IAR to look for your USB stick and not a port on your computer.
- Change the Target VCC option at the bottom of the screen to 3.0
- Click OK to finalize your settings. You are now ready to build and compile your project.
Step 3 – Running the Program
Before we compile the project, make sure to save your project to preserve its settings. Select the add_primes.s43 file in the workspace window and click Project -> Compile. Alternatively, you can right click on the source file and select Compile. When the workbench is finished compiling your source code, you will see a new window at the bottom of the screen called your Build Messages Window. It should say that there are 0 errors and 0 warnings.Figure 4
The "build message" window
To see what happens when your code contains an error, erase one of the semicolons preceding a comment in the add_primes.s43 code and re-compile. The build message window displays:- Any errors/warnings in your code
- The assembler’s best attempts of an explanation
- The name of the files in which the errors/warnings occurred
- The line number where the errors/warnings occurred
Double click the line that says “Error[0]: Invalid syntax.” In the file, your cursor will be placed close to the location of the error. Fix the error, and then re-compile.Now make sure that your EZ430 is plugged in and click Project -> Debug. This will run your code on the EZ430 and put you in debugging mode.Step 4 – Debugging A Project
A new window has been added to the screen in debugging mode. It is called the Disassembly Window. After the assembler compiles your code into machine code, a disassembler program does the opposite and creates the contents of the disassembly window. You can apply the debugging commands to either the coded assembly file or the disassembly window. Generally, this tool is more useful when the developer has written his/her application using the C programming language and wants to see how the machine interpreted his/her code in assembly.The workbench allows users to move and dock windows as they wish. To see this, click View -> Memory and View -> Registers. Click on the window labels to drag and dock them in the same tab group as the Debug Log and Buildwindows. These windows are updated as the program executes, giving the user extremely useful insight to the inner workings of his/her program.NOTE: If the contents of the window selected in each tab group ever change, the changed contents will be highlighted red to show the change.The Memory Window
The memory window allows the user to navigate the entire memory map of the MSP430. Since we used assembler directives to load the array of prime numbers starting at memory location 0200h, type 0x0200 into the Go to box. You will see the array stored in consecutive words in memory.Figure 5
Memory Window
Instead of Memory, IAR also gives you the option to looking at:- SFR: The special function and peripheral registers
- RAM: Memory
- INFO: Information FLASH memory (ROM)
- FLASH: Main FLASH memory (ROM)
NOTE_01: You can use the information and main memories just the same. The only difference is how the memory is physically segmented and the address.NOTE_02: If you look at the FLASH memory, notice that this is where the main program is stored. The numbers you see are the instructions of the program that have been stored for program execution.The Register Window
The register window shows the user any of the important registers whether they be peripheral control registers, special function registers, or just the basic CPU registers. For the most part, you will only be interested in the CPU Registers, but know that the other registers are available for viewing. Also note that the Status Register (SR) containing the status bits can be expanded to see each individually labeled bit.While stepping through the program, periodically check the Memory and Register windows to see how they change according to your code.Inspecting Source Statements
Run your mouse over these buttons in the top left corner of your debugging session and read their function in the bottom left corner of the IAR workbench frame.Figure 6
The Debug Buttons
(a)
(b) Program Reset Resets the execution of your program. Takes you back to the instruction address located in the reset interrupt vector.
(c) Step Over - Steps over the current step point.
(d) Step Into - When you debug a program with subroutines in assembly, you can choose to “Step Over” the subroutines, meaning that the subroutine is executed but you don’t step through it in the debugger, or you can choose to “Step Into” the subroutine. Stepping into a subroutine will allow the user to see the individual op-codes executed.
(e) Step Out Of - If you have stepped into a subroutine, steps out of the subroutine and to the next instruction after the subroutine call.
(f) Step to Next - Steps to the next statement, regardless of the circumstances.
(g) Execute to Current Cursor Position - Executes the program to the line at which the cursor is currently located.
(h) Run - Runs the program straight through or until a breakpoint.
(i) Stop Debugging - Stops the debugging session returns the user to programming mode. At the top right-hand side of the page, note this button as well:
(j) Make and Reset - Press when code has been modified so that it needs to be re-compiled and the debugger needs to be reset.
Breakpoints
Sometimes it is beneficial, if you want to know how your program is executing at a certain point in its execution, to use breakpoints. To place a breakpoint in the program, double click on the margin next to the line at which you wish to set a breakpoint (or right click on the line and select toggle breakpoint (conditional)).For example, the initial operators in every assembly code project that initialize the controller after a Power Up Clear can often be assumed to work properly. If you would like to run the program starting immediately after this section of code, add a breakpoint at the line labeled main. Since we have two clear operators in the beginning of our code that we know will work, place a breakpoint at the first mov.w instruction line of the main program. Press the Program Reset button to restart program execution and then press the Run to execute until the breakpoint. From here on, play with the other buttons to gain some intuition as to their function.NOTE: Debugging can also be done in the disassembly window. Try it out and see if you can follow what all the numbers mean in regards to the CPU registers and memory.For more information on debugging, reference the EZ430_UserGuide. An in-depth understanding of the debugging module is a truly powerful tool for future programming.After completing this tutorial, you should feel comfortable working with the IAR Embedded Workbench. If you do not, you may want to go back and do it again. Also, make sure you have read and understand the material from lab section 3.2. It will be critical to the execution of future labs.3.5 – Procedure
1. Set up the EZ430, IAR Embedded Workbench, and all necessary hardware.2. Complete the tutorial.Call the lab TA and repeat the tutorial in their presence, without reading the directions. When you can do this without looking at the instructions, the TA will check you off. Review any part of this lab you are not sure about.3.6 – Questions
- Describe the register set for the MSP430F2012. What are the Special Function Registers (SFRs) and their functions? Where are they located?
- How are single stepping and breakpoints used to debug a program? Why might you use breakpoints rather than single stepping?
- In the “Disassembler” window, what do the numbers on the far left mean? What does this have to do with the contents in R0 during program execution?
3.7. – Lab Report
The lab report is due at the beginning of the next lab. For the lab write up, include the following:- Your marked up version of this document.
- A brief discussion of the objectives of the lab and the procedures performed in the lab.
- Answer to any questions in the discussion, procedure or question sections of the lab.
Bibliography
"Msp430x2xx Family User's Guide." Dallas, Texas: Texas Instruments Incorporated, 2005.
Look Up Tables for MSP430 in C
Summary: Microcontrollers have a limited amount of memory in which variable data can be stored. In some cases, it is necessary to store and access large quantities of data, such as a lookup table, for use within a progam. If this data will not be changed by the program during run time, it can be stored in the read only section of memory.
To locate an array in read only memory rather than in RAM, declare and assign it as a constant.const int DegFRTD[] = {-500, -40, -39, -38, -37, -36, -35, -34, -33,
-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20,
-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6,
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
211, 212, 999, 999};
const long OhmRTD[] = {0,8427, 8450, 8471, 8493, 8515, 8537, 8559, 8581,
8603, 8625, 8647, 8669, 8691, 8713, 8735, 8757, 8779, 8801, 8822, 8844, 8866,
8888, 8910, 8932, 8954, 8976, 8998, 9019, 9041, 9063, 9085, 9107, 9129, 9151,
9172, 9194, 9216, 9238, 9260, 9282, 9303, 9325, 9347, 9369, 9391, 9413, 9434,
9456, 9478, 9500, 9522, 9543, 9565, 9587, 9609, 9630, 9652, 9674, 9696, 9718,
9739, 9761, 9783, 9805, 9826, 9848, 9870, 9891, 9913, 9935, 9957, 9978, 10000,
10022, 10043, 10065, 10087, 10109, 10130, 10152, 10174, 10195, 10217, 10239,
10260, 10282, 10304, 10325, 10347, 10369, 10390, 10412, 10434, 10455, 10477,
10498, 10520, 10542, 10563, 10585, 10607, 10628, 10650, 10671, 10693, 10715,
10736, 10758, 10779, 10801, 10822, 10844, 10866, 10887, 10909, 10930, 10952,
10973, 10995, 11017, 11038, 11060, 11081, 11103, 11124, 11146, 11167, 11189,
11210, 11232, 11253, 11275, 11296, 11318, 11339, 11361, 11382, 11404, 11425,
11447, 11468, 11490, 11511, 11533, 11554, 11575, 11597, 11618, 11640, 11661,
11683, 11704, 11725, 11747, 11768, 11790, 11811, 11833, 11854, 11875, 11897,
11918, 11940, 11961, 11982, 12004, 12025, 12046, 12068, 12089, 12111, 12132,
12153, 12175, 12196, 12217, 12239, 12260, 12281, 12303, 12324, 12345, 12367,
12388, 12409, 12431, 12452, 12473, 12494, 12516, 12537, 12558, 12580, 12601,
12622, 12643, 12665, 12686, 12707, 12728, 12750, 12771, 12792, 12813, 12835,
12856, 12877, 12898, 12920, 12941, 12962, 12983, 13005, 13026, 13047, 13068,
13089, 13111, 13132, 13153, 13174, 13195, 13216, 13238, 13259, 13280, 13301,
13322, 13343, 13365, 13386, 13407, 13428, 13449, 13470, 13491, 13513, 13534,
13555, 13576, 13597, 13618, 13639, 13660, 13681, 13702, 13724, 13745, 13766,
13767, 13808, 13829, 13850, 1000000, 1000000};
Data constants that do not need to be indexed can be stored as a constant, but they can also be defined by a preprocessor directive so that the preprocessor simply substitutes in the number where the name of the constant is used before the code is compiled. The value can be changed in each location it is used by simply changing the preprocessor directive in one place, saving time and reducing errors.
#define pi (3.14159) //preprocessor directive
float circumference;
float diameter;
void main (void)
{
circumference = pi*diameter; // The preprocessor translates this into circumference = 3.14159 * diameter;
}
3.1 - Objectives
This introductory lab will walk you through the process of creating an assembly project, assembling a program, downloading it to the EZ430 (the development kit for the TI-MSP430F2012) and executing / debugging the program. When you complete this lab, you should be able to:
- Understand the IAR Embedded Workbench IDE.
- Assemble (build) a program using the IAR Embedded Workbench.
- Download a program onto your EZ430.
- Run a program and examine memory registers.
- Use stepping and breakpoints to debug the program.
Because you will perform all of these procedures in every lab you do after this, a complete understanding of the material in this lab is necessary.
3.2 - Reading Material
You will need to read the following introduction material prior to completing this lab, all are available on the ECE 251 website.
- Introduction to the MSP430-F2012 controller
- Introduction to assembly programming
- MSP430 Instruction Reference Sheet
3.3 - Hardware / Software Setup
The eZ430 debugger/emulator should install its drivers automatically. To install IAR Embedded Workbench Kickstart Version, please visit www.ti.com or www.iar.com for the latest version of the software with installation instructions.
3.4 - Introduction to IAR Embedded Workbench IDE
Invoke the IAR Embedded Workbench in one of the following two ways:
- Left click your mouse on the START menu on the bottom left of your screen. Then follow the path, Programs -> IAR Systems -> IAR Embedded Workbench Kickstart for MSP430 V4.1-> IAR Embedded Workbench.
- Open Windows explorer and locate IAR Embedded Workbench.exe in the folder C:\Program Files\IAR Systems\Embedded Workbench 4.1\common\bin\IarIdePm.exe
To create the shortcut on your desktop, right click the mouse on IarIdePm.exe and then left click on create shortcut. Then click on this shortcut to invoke the IAR Embedded Workbench application.
Step 1 – Creating a Project
The first thing you will see is the Embedded Workbench Startup screen. This screen will be a good shortcut to open existing workspaces and create new projects in the future, but for now, click the Cancel button. Note that a workspacecan hold one or more projects, each which can hold groups of source files (the files that contain your assembly code).
Click on File -> New -> Workspace. This opens a new workspace in which to place your projects. You must always open a workspace before you can create a new project. To create a new project, click Project -> Create New Project… TheCreate New Project box will appear. IAR lets you choose whether you want to create an assembly (asm), C, or C++ project. Expand the asm tab and click OK once you have selected the asm option.
New Project Window |
---|
IAR will ask you to specify where you would like to save your .ewp project file. It is recommended you create a folder for your workspaces on your u: drive such as u:\ee251\Labs\ in which you can store all your future labs. Create a folder calledLab 3, name your project Lab 3, and click Save. At this point, you should also download the add_primes.s43 file provided on the class webpage into the same folder.
Look at the left of your screen. You will see the workspace window where your projects and source files are organized.
Workspace Window |
---|
On the right is the project window. The project window shows the assembly file template discussed in Introduction To Assembly Programming from the pre-lab material. You will not be using this file for this tutorial. Before anything else, click on File -> Save Workspace and save your workspace in the same folder as the project.
Now add the file we are going to examine in the tutorial. In your workspace window, right click on the project name and select Add -> Add Files… At the bottom of the page, change the Files of type tab to the Assembler Files option. If you downloaded the file from the class webpage, go ahead and select the add_primes.s43 file and click Open. You should see the file added to your workspace window. Right click on the asm.s43 template and remove it from the project then take a look at the add_primes.s43 code. This assembly program has stored the first six prime numbers in an array in memory and adds them up into register six. See if you understand what is going on by referencing the pre-lab material.
Step 2 – Setting the Project Options
Before we can compile our code into an executable object file, we need to set the project options. Using the Project pull-down menu select Options or simply right click on the project and select Options… This will bring you to the Options for node “<project_name>” screen.
Project Options Screen |
---|
- In the General Options menu:
- Set the Device to the MSP430F2012 or whatever MSP430 device number you are using.
- In the Debugger menu:
- Set the Driver to FET Debugger. This makes sure that once compiled into an object file, the program will be loaded onto your physical microcontroller, not the IAR simulator.
- If you would ever like to work on your code but you do not have your EZ430, you can set the Driver option to Simulator and the IAR Embedded Workbench will simulate your microcontroller.
- Under the actual FET Debugger menu:
- Change the Connection from LPT -> LPT1 to TI USB FET. This tells IAR to look for your USB stick and not a port on your computer.
- Change the Target VCC option at the bottom of the screen to 3.0
- Click OK to finalize your settings. You are now ready to build and compile your project.
Step 3 – Running the Program
Before we compile the project, make sure to save your project to preserve its settings. Select the add_primes.s43 file in the workspace window and click Project -> Compile. Alternatively, you can right click on the source file and select Compile. When the workbench is finished compiling your source code, you will see a new window at the bottom of the screen called your Build Messages Window. It should say that there are 0 errors and 0 warnings.
The "build message" window |
---|
To see what happens when your code contains an error, erase one of the semicolons preceding a comment in the add_primes.s43 code and re-compile. The build message window displays:
- Any errors/warnings in your code
- The assembler’s best attempts of an explanation
- The name of the files in which the errors/warnings occurred
- The line number where the errors/warnings occurred
Double click the line that says “Error[0]: Invalid syntax.” In the file, your cursor will be placed close to the location of the error. Fix the error, and then re-compile.
Now make sure that your EZ430 is plugged in and click Project -> Debug. This will run your code on the EZ430 and put you in debugging mode.
Step 4 – Debugging A Project
A new window has been added to the screen in debugging mode. It is called the Disassembly Window. After the assembler compiles your code into machine code, a disassembler program does the opposite and creates the contents of the disassembly window. You can apply the debugging commands to either the coded assembly file or the disassembly window. Generally, this tool is more useful when the developer has written his/her application using the C programming language and wants to see how the machine interpreted his/her code in assembly.
The workbench allows users to move and dock windows as they wish. To see this, click View -> Memory and View -> Registers. Click on the window labels to drag and dock them in the same tab group as the Debug Log and Buildwindows. These windows are updated as the program executes, giving the user extremely useful insight to the inner workings of his/her program.
NOTE: If the contents of the window selected in each tab group ever change, the changed contents will be highlighted red to show the change.
The Memory Window
The memory window allows the user to navigate the entire memory map of the MSP430. Since we used assembler directives to load the array of prime numbers starting at memory location 0200h, type 0x0200 into the Go to box. You will see the array stored in consecutive words in memory.
Memory Window |
---|
Instead of Memory, IAR also gives you the option to looking at:
- SFR: The special function and peripheral registers
- RAM: Memory
- INFO: Information FLASH memory (ROM)
- FLASH: Main FLASH memory (ROM)
NOTE_01: You can use the information and main memories just the same. The only difference is how the memory is physically segmented and the address.
NOTE_02: If you look at the FLASH memory, notice that this is where the main program is stored. The numbers you see are the instructions of the program that have been stored for program execution.
The Register Window
The register window shows the user any of the important registers whether they be peripheral control registers, special function registers, or just the basic CPU registers. For the most part, you will only be interested in the CPU Registers, but know that the other registers are available for viewing. Also note that the Status Register (SR) containing the status bits can be expanded to see each individually labeled bit.
While stepping through the program, periodically check the Memory and Register windows to see how they change according to your code.
Inspecting Source Statements
Run your mouse over these buttons in the top left corner of your debugging session and read their function in the bottom left corner of the IAR workbench frame.
The Debug Buttons | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Breakpoints
Sometimes it is beneficial, if you want to know how your program is executing at a certain point in its execution, to use breakpoints. To place a breakpoint in the program, double click on the margin next to the line at which you wish to set a breakpoint (or right click on the line and select toggle breakpoint (conditional)).
For example, the initial operators in every assembly code project that initialize the controller after a Power Up Clear can often be assumed to work properly. If you would like to run the program starting immediately after this section of code, add a breakpoint at the line labeled main. Since we have two clear operators in the beginning of our code that we know will work, place a breakpoint at the first mov.w instruction line of the main program. Press the Program Reset button to restart program execution and then press the Run to execute until the breakpoint. From here on, play with the other buttons to gain some intuition as to their function.
NOTE: Debugging can also be done in the disassembly window. Try it out and see if you can follow what all the numbers mean in regards to the CPU registers and memory.
For more information on debugging, reference the EZ430_UserGuide. An in-depth understanding of the debugging module is a truly powerful tool for future programming.
After completing this tutorial, you should feel comfortable working with the IAR Embedded Workbench. If you do not, you may want to go back and do it again. Also, make sure you have read and understand the material from lab section 3.2. It will be critical to the execution of future labs.
3.5 – Procedure
1. Set up the EZ430, IAR Embedded Workbench, and all necessary hardware.
2. Complete the tutorial.
Call the lab TA and repeat the tutorial in their presence, without reading the directions. When you can do this without looking at the instructions, the TA will check you off. Review any part of this lab you are not sure about.
3.6 – Questions
- Describe the register set for the MSP430F2012. What are the Special Function Registers (SFRs) and their functions? Where are they located?
- How are single stepping and breakpoints used to debug a program? Why might you use breakpoints rather than single stepping?
- In the “Disassembler” window, what do the numbers on the far left mean? What does this have to do with the contents in R0 during program execution?
3.7. – Lab Report
The lab report is due at the beginning of the next lab. For the lab write up, include the following:
- Your marked up version of this document.
- A brief discussion of the objectives of the lab and the procedures performed in the lab.
- Answer to any questions in the discussion, procedure or question sections of the lab.
Bibliography
"Msp430x2xx Family User's Guide." Dallas, Texas: Texas Instruments Incorporated, 2005.
Look Up Tables for MSP430 in C
Summary: Microcontrollers have a limited amount of memory in which variable data can be stored. In some cases, it is necessary to store and access large quantities of data, such as a lookup table, for use within a progam. If this data will not be changed by the program during run time, it can be stored in the read only section of memory.
To locate an array in read only memory rather than in RAM, declare and assign it as a constant.const int DegFRTD[] = {-500, -40, -39, -38, -37, -36, -35, -34, -33,
-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20,
-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6,
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
211, 212, 999, 999};
const long OhmRTD[] = {0,8427, 8450, 8471, 8493, 8515, 8537, 8559, 8581,
8603, 8625, 8647, 8669, 8691, 8713, 8735, 8757, 8779, 8801, 8822, 8844, 8866,
8888, 8910, 8932, 8954, 8976, 8998, 9019, 9041, 9063, 9085, 9107, 9129, 9151,
9172, 9194, 9216, 9238, 9260, 9282, 9303, 9325, 9347, 9369, 9391, 9413, 9434,
9456, 9478, 9500, 9522, 9543, 9565, 9587, 9609, 9630, 9652, 9674, 9696, 9718,
9739, 9761, 9783, 9805, 9826, 9848, 9870, 9891, 9913, 9935, 9957, 9978, 10000,
10022, 10043, 10065, 10087, 10109, 10130, 10152, 10174, 10195, 10217, 10239,
10260, 10282, 10304, 10325, 10347, 10369, 10390, 10412, 10434, 10455, 10477,
10498, 10520, 10542, 10563, 10585, 10607, 10628, 10650, 10671, 10693, 10715,
10736, 10758, 10779, 10801, 10822, 10844, 10866, 10887, 10909, 10930, 10952,
10973, 10995, 11017, 11038, 11060, 11081, 11103, 11124, 11146, 11167, 11189,
11210, 11232, 11253, 11275, 11296, 11318, 11339, 11361, 11382, 11404, 11425,
11447, 11468, 11490, 11511, 11533, 11554, 11575, 11597, 11618, 11640, 11661,
11683, 11704, 11725, 11747, 11768, 11790, 11811, 11833, 11854, 11875, 11897,
11918, 11940, 11961, 11982, 12004, 12025, 12046, 12068, 12089, 12111, 12132,
12153, 12175, 12196, 12217, 12239, 12260, 12281, 12303, 12324, 12345, 12367,
12388, 12409, 12431, 12452, 12473, 12494, 12516, 12537, 12558, 12580, 12601,
12622, 12643, 12665, 12686, 12707, 12728, 12750, 12771, 12792, 12813, 12835,
12856, 12877, 12898, 12920, 12941, 12962, 12983, 13005, 13026, 13047, 13068,
13089, 13111, 13132, 13153, 13174, 13195, 13216, 13238, 13259, 13280, 13301,
13322, 13343, 13365, 13386, 13407, 13428, 13449, 13470, 13491, 13513, 13534,
13555, 13576, 13597, 13618, 13639, 13660, 13681, 13702, 13724, 13745, 13766,
13767, 13808, 13829, 13850, 1000000, 1000000};
Data constants that do not need to be indexed can be stored as a constant, but they can also be defined by a preprocessor directive so that the preprocessor simply substitutes in the number where the name of the constant is used before the code is compiled. The value can be changed in each location it is used by simply changing the preprocessor directive in one place, saving time and reducing errors.
#define pi (3.14159) //preprocessor directive
float circumference;
float diameter;
void main (void)
{
circumference = pi*diameter; // The preprocessor translates this into circumference = 3.14159 * diameter;
}
const int DegFRTD[] = {-500, -40, -39, -38, -37, -36, -35, -34, -33,
-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20,
-19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6,
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
211, 212, 999, 999};
const long OhmRTD[] = {0,8427, 8450, 8471, 8493, 8515, 8537, 8559, 8581,
8603, 8625, 8647, 8669, 8691, 8713, 8735, 8757, 8779, 8801, 8822, 8844, 8866,
8888, 8910, 8932, 8954, 8976, 8998, 9019, 9041, 9063, 9085, 9107, 9129, 9151,
9172, 9194, 9216, 9238, 9260, 9282, 9303, 9325, 9347, 9369, 9391, 9413, 9434,
9456, 9478, 9500, 9522, 9543, 9565, 9587, 9609, 9630, 9652, 9674, 9696, 9718,
9739, 9761, 9783, 9805, 9826, 9848, 9870, 9891, 9913, 9935, 9957, 9978, 10000,
10022, 10043, 10065, 10087, 10109, 10130, 10152, 10174, 10195, 10217, 10239,
10260, 10282, 10304, 10325, 10347, 10369, 10390, 10412, 10434, 10455, 10477,
10498, 10520, 10542, 10563, 10585, 10607, 10628, 10650, 10671, 10693, 10715,
10736, 10758, 10779, 10801, 10822, 10844, 10866, 10887, 10909, 10930, 10952,
10973, 10995, 11017, 11038, 11060, 11081, 11103, 11124, 11146, 11167, 11189,
11210, 11232, 11253, 11275, 11296, 11318, 11339, 11361, 11382, 11404, 11425,
11447, 11468, 11490, 11511, 11533, 11554, 11575, 11597, 11618, 11640, 11661,
11683, 11704, 11725, 11747, 11768, 11790, 11811, 11833, 11854, 11875, 11897,
11918, 11940, 11961, 11982, 12004, 12025, 12046, 12068, 12089, 12111, 12132,
12153, 12175, 12196, 12217, 12239, 12260, 12281, 12303, 12324, 12345, 12367,
12388, 12409, 12431, 12452, 12473, 12494, 12516, 12537, 12558, 12580, 12601,
12622, 12643, 12665, 12686, 12707, 12728, 12750, 12771, 12792, 12813, 12835,
12856, 12877, 12898, 12920, 12941, 12962, 12983, 13005, 13026, 13047, 13068,
13089, 13111, 13132, 13153, 13174, 13195, 13216, 13238, 13259, 13280, 13301,
13322, 13343, 13365, 13386, 13407, 13428, 13449, 13470, 13491, 13513, 13534,
13555, 13576, 13597, 13618, 13639, 13660, 13681, 13702, 13724, 13745, 13766,
13767, 13808, 13829, 13850, 1000000, 1000000};
#define pi (3.14159) //preprocessor directive
float circumference;
float diameter;
void main (void)
{
circumference = pi*diameter; // The preprocessor translates this into circumference = 3.14159 * diameter;
}
0 comments:
Post a Comment