In this lab we are going to use MPLAB® X IDE and its associated XC32 compiler to write and debug an assembler program for the PIC32, a microcontroller based on the MIPS32 architecture. The MPLAB X software is NetBeans based and will run under Linux, Mac and Windows.
You can download your own copy of MPLAB X from Microchip’s MPLAB X download page. You will need to install the following:
- MPLAB X IDE – v3.35 is installed in the lab
- MPLAB XC 32 Compiler – v1.42 is installed in the lab
You can get a short list of instructions from the MIPS “Green Card”. Section 2 of the PIC32 Family Reference Manual, CPU for Devices with M4K core. If you want 330 pages about MPLAB X, check out the MPLAB® X IDE User’s Guide. The definitive guide to the XC32 assembler is the 234 page MPLAB® XC32 Assembler, Linker and Utilities User’s Guide. Information relevant to the assembler is also contained in the MPLAB® XC32 C/C++ User’s Guide.
Getting Started
From the command line you can type mplab_ide or you can type “mplab” in the search box at the top of the launcher. Be sure to select MPLAB IDE and not MPLAB IPE. (IPE is Integrated Programming Environment. In embedded system design, “programming” is the process of downloading code to the chip.)
If you’ve used NetBeans, you’ll feel at home with. MPLAB X.
First Project in MPLAB X
Creating the project
Use the menu choices File ⇒ New Project... to begin the process of creating a project. Then work your way through a few windows.
- In the Choose Panel window, from the Microchip Embedded category choose a Standalone Project.
- In the Select Device window, select any device from the 32-bit MCUs (PIC32) family. I chose PIC32MX250F256H. Next time you’ll be able to speed up this process by choosing the Recently Used family.
- In the Select Tool window, go for the Simulator.
- In the Select Compiler window, select a XC 32. There should be only one choice.
- In the Select Project Name and Folder window, think of a clever project name and and click Set as main project.
You can click on the following images, if you think they are too small.
You may have noticed that many of selected choices were preceded by a little green dot. Avoid the ones with the red and yellow dots.
Let’s mention a couple of things before going on.
There were a lot of devices to choose from. If you are using the simulator, as we are today, you don’t have to be that precise in your selection, but usually you must choose the device the that matches the one you plan is use in your project.
The XC 32 is Microchip’s latest compiler for its 32-bit processors. We are using the free (unlicensed) version. The free compiler is based on the gcc toolchain and it does not optimize your C code. It will cost you about $1000 to get the optimizing “PRO” compiler.
Also, notice that your projects are going to be stored in directories with names that end with a capital X, such as CSCI255rocks.X .
Right-click on the name of your project and then select Properties. Make sure you have chosen well.
Checking it out the IDE
At this point you have a NetBeans environment that will be familiar to alumni of CSCI 181 and 202. Move your mouse over the menu choices at the top of the window, from File to Help. Press on the choices to look at their submenus. Pay particular attention to items under Debug. Most of the choices are presently grayed out, because they can’t be used until you are working on a project.
Notice that the lower left corner is occupied by a Dashboard display. The Microchip PIC devices have very little memory so we need an easy-to-use means of figuring out how much memory our programs are using.
Adding an assembler program
Now we’ll use the menu to create an assembler program. Start with the menu choices File ⇒ New File...
- In the Choose File Type window, take category Assembler category and type AssemblyFile.s . You must to make the .s choice.
- In the Name and Location window, choose a name for your file. I suggest something like whatever . MPLAB X will add the .s to your filename.
At this point, you should have an empty program in the upper-right window. Make sure that your program really is under Source Files.
Copy the following program into your empty window. Take care that your program ends with a CRLF.
#include <xc.h> .global main .data a: .int 2 b: .int 8 c: .int 17 x: .int 10 z: .int -1 .text .set noreorder .ent main main: ## z = a*x*x + b*x + c ## $t0 = a lw $t0,a ## $t1 = b ## $t2 = c ## $t3 = x ## $t4 = a*x mul $t4,$t0,$t3 ## $t4 = $t4*x ## $t5 = b*x ## $t4 = $t4+$t5 add $t4,$t4,$t5 ## $t4 = $t4+c ## z = $t4 spin: j spin nop .end main
Go ahead and press the hammer to built it so we can make sure your installation is working.
This program is the start of an assembly language implementation of the following statement which can be in Java, C++, C, Python, JavaScript, ....
z = a*x*x + b*x + c
What’s it all about
But clearly this isn’t Java, C++, C, Python, or even JavaScript.
Let’s look at this program for a minute. Like most assembly language programs, this one contains several pseudo-ops or directives. These are lines of code that don’t create instructions. They may define space for variables or control the assembly process or even control the spacing for a printout of your code.
System files
The program starts with the directive:
#include <xc.h>
which would a legal statement in either C++ or C.
This causes the assembler to include a file defining useful constants
for programming PIC microcontrollers.
Open the file
/opt/microchip/xc32/v1.42/pic32mx/include/xc.h in MPLAB X using
File ⇒
Open File...
(That took a little time, didn t it.)
That one isn’t that interesting. It’s just a list of include files
for several different PIC processors. Try again, but this time open
/opt/microchip/xc32/v1.42/pic32mx/include/proc/p32mx250f256h.h in MPLAB X.
Using
Edit ⇒
Find... or simply
Ctrl+F find the definition of
PORTB
, the special function register you used in the
Arduino lab.
The volatile
keyword is common to Java and C and denotes a variable
that can be changed by external forces.
__attribute__
is an
extension of GNU CC that is rarely encountered in
user programs.
The __attribute__((section("sfrs")))
indicates that
PORTB
is a special function register.
We are serious. You need to know how to navigate the file system from
the IDE. Show us the line defining PORTB
.
Segments
Now close those two big system .h files and get back to your program.
The second line in your program is also a directive:
.global main
This causes the assembler to announce
main
as an external variable of your program.
This means that the outside “world” will know about
main
.
This is a bit like declaring a method public
in Java.
Since ancient times, running programs have been considered to consist of four segments:
(1) the text segment, which contains compiled code;
(2) the stack segment, which contains local variables used by functions or methods;
(3) the heap segment, which contains dynamically allocated memory, such as Java objects; and
(4) the data segment, which contains global variables. The data area also contains the oddly name bss (block started by symbol) segment which contains space for uninitialized data.
In this program, you see that both a text and data segment are defined.
The data segment reserves room for the five variables
a
, b
, c
and z
.
The text segment contains the PIC instructions.
Executing a program
The Microchip simulator does know how to simulate the PIC instructions of your program, but right now your program does little more than loop forever. To see anything interesting you must step through the program.
Getting ready to run
To do this you need to know how to set breakpoints in
your program.
Move your mouse onto the narrow column of program line numbers just
to the left of the first real instruction,
the lw
, of your program and click.
There should put a little red square in the line number column
and highlight the entire line in red to show that you have
set a breakpoint.
Now use the menu choices
Debug
⇒
Debug Main Project. This should start the
simulation but stop at the breakpoint.
Put the break in your program and run your program to the breakpoint. If you have done this before using NetBeans, help out any lab neighbors who haven’t.
You will notice a bunch of new tabs in the lower right panel.
One of them is called
Variables.
Go over to the Variables tab
and add a watch for all your variables.
This is a little non-intuitive. You need to clink on
<Enter new watch> and then
enter the variable name.
However, all the action if with the registers.
Use the window menu choices
Window ⇒
PIC Memory Views
⇒ CPU Registers
to bring up a new tab called CPU Memory.
Use the arrow keys to find registers $t0
to $t5
in this display.
These registers are also known as
$r08
to $r12
.
By checking within the Hex or CPU Registers columns, you can change the values of registers.
Set the values of
registers $t0
and $t5
.
Now use
Window ⇒
PIC Memory Views
⇒ Execution Memory
to see your assembly code translated into machine code
in the Opcode column.
The lw
assembly language statement has
been translated into a two-instruction machine language sequence.
We will explain that in class.
Completing the program
Right now only three of the ten simple assignment statements have been completed. Complete the remaining seven and build your program.
You will need to use the sw
instruction for the last
assignment.
Debugging with the simulator
It’s time to run some code. Use the F8 key to step through your program while looking at the CPU Registers to see changes in the registers.
Step through the program one instruction at a time. After each instruction, verify that the expected result has been stored in the destination register.
In case of trouble
In the last few years, you wouldn’t get the expected results
due to the way the mul
instruction was handled in the
simulator.
That no longer seems to be the case. It appears the old simulator
was broken.
However if there is a problem, go back to the end of the old lab and work on the part about delay slots.
In case time remains
If time permits, add four new variables n
, o
,
p
and e
to your program and implement the following
two C statements with code placed right before the spin
label:
n = (c & 0xFFF) << 2 ; o = 3 * x + 1 ; p = a < b ; e = ~c ;
Use immediate instructions to implement the statements. Use the PIC32 reference table to find the instructions needed for your program. It’s mostly a matter of matched the C operator with the appropriate MIPS32 instruction.
In case of trouble....
If your windows get completely messed up, try some of the following:
- Window ⇒ Reset Windows
- Window ⇒ Output ⇒ Output
- Window ⇒ Debugging ⇒ Variables