Lab 2: MPLAB Introduction

Effective 9/30/24: This lab is being revised for Spring 2025 and may differ slightly from the lab you performed. Contact Peter Loux (prl83@msstate.edu) if you have questions.

TODO:

This lab introduces you to the Microchip MPLAB X Integrated Design Environment. The objectives of this lab are:

As always, read/scan through the entire lab before starting to work.

Basics

The following sections will cover basic usage of MPLAB X IDE 6.20:

Opening a project

To open a project, go to File > Open Project...

For these examples, I will be using the project C:\ece3724\pic24_code_examples\chap03\mptst_byte.X. Feel free to open it and follow along.

Closing a project

To close a project, choose the appropriate option from the File menu. To close a file, just click the X in the editor tab. Closing a file does not close a project and vice versa. A common error is to be working on a file that is not part of the project you are compiling. No matter what you do to the file, it won't fix your program! To avoid this frustrating problem, it is highly recommended that you only keep one project open at a time. If you need to look at other files that aren't in the project, just open them separately. If you absolutely must have multiple projects open, be sure to set the one you're trying to compile as the main project.

Opening an assembly source file

The assembly source files (the code) will be in the Source Files folder of the project. Doubleclick to open them in the editor:

Adding a file to a project

It is a pain in the neck to create a new MPLAB project. You have to be sure that all the header files and libraries from pic24_code_examples are included and that the makefile is configured correctly. Copying an existing project is somewhat easier, but you can run into trouble doing this as well. So in lab, follow these steps when you want to begin something new:

1. Open an existing project.

2. Then either:

a. Add a provided file (like lab code you've downloaded from Canvas) or

b. Create a new file.

Do not open up an existing file from pic24_code_examples or one of your completed labs and start modifying it. Why not? Because if you change it and suddenly start getting a bunch of errors, you don't know whether the problem is buggy code, your computer, MPLAB, the PIC, etc. (Instead, when you're writing code and get completely stuck, go back to one of these known good files and make sure it still runs. If it doesn't, then you've got bigger issues.

Running (debugging) a project

To debug (run in the MPLAB simulator) the project, click the button that looks like a piece of paper with a play button on the lower right corner.

The red square next to it - you guessed it - stops the debugger. You can also go to Debug > Debug Main Project or Debug > Finish Debugger Session through the menu.

I've set F5 as my Debug Main Project shortcut key. To do this, go to Tools > Options > Keymap

Viewing program memory

To view program memory,  Window -> Target Memory Views -> Program Memory.

This opens up a tab at the bottom where you can view the (virtual) PIC's program memory.

Try switching the Format from Code to Hex (and then back, unless you're a computer). Right-click somewhere in the program memory, and make sure Symbolic Mode and Verbose Labels are checked. They also make it a lot easier to read. Uncheck/recheck them and try to figure out why.

Viewing data memory (file registers)

Data memory is called "File Registers" in MPLAB. If you click Memory on the bottom right of the Program Memory tab, it opens up a dropdown. If you select File Registers, this will show data memory in that tab instead. If you want to have both open at the same time, then Window > Target Memory Views > File Registers.

Format: Symbol makes this easier to read. For example, you can see the registers, starting at 0x0000, and below, starting at 0x1000, the variables in the program. Instead of scrolling through, you can click the magnifying glass below the output tab and search for line 1000. 

Notice that it doesn't show u8_j, because that's at 0x1001.

Viewing registers

In MPLAB, instead of W0-W15, the working registers are called WREG0 - WREG15. All the registers with names are referred to as SFRs, or Special Function Registers. There's a number of ways to view their contents. One is by going to address 0x0000 of data memory, as mentioned above:

You can also Window -> Target Memory Views -> SFRs:

However, generally we're interested in only a few of the working registers. Also we might want to look at the values of some variables as well, and we'd like to do all this without scrolling back and forth through memory locations. Fortunately, there's a way to do this - setting Watches!

Setting Watches

To get the Watches tab to show up, you Window -> Debugging -> Watches (or just Alt-Shift-2).

The Variables tab is very similar to the Watches tab, but it also lets you view local variables i.e. variables that are created inside a function and then vanish when the function exits. (https://developerhelp.microchip.com/xwiki/bin/view/software-tools/ides/x/debugging/accessing-data/watches-vs-variables/)

To add a variable or register you want to watch, right click in the Watches tab. Another way to add expressions to the Watch window is to right-click in the source code and select "New Watch..." 

You can also highlight variables to save typing, or select multiple expressions at the same time:

Variables are found in Global Symbols. Registers are found in SFR's (Special Function Registers). Important: To watch a working register, add WREG#. For example, to watch W2, select WREG2. If you're not able to add variables to the Global Symbols list, debug the program once first and try again.

If we look through mptst_byte, we can see it uses 3 variables (u8_i, u8_j, and u8_k), and 2 registers (W0 & W1 aka WREG0 & WREG1). So, if you're following along, add those to your watches:

To get the extra columns to show up, right click in the bar atop the watches that says "Name Type  Address ..." and check the ones you want to see.

The last two lines of this program (visible in the above picture) just loop endlessly, doing nothing. So the watches are showing the final values in the registers and variables at the very end of the program. But what if our program screws up somewhere along the way and we want to find out where we went wrong? That is what breakpoints are for, and it's the last thing you need to know about in MPLAB, at least in order to do the prelab.

Breakpoints

A breakpoint is a place we want our program to pause its execution so we can examine memory and register contents in midstream. Setting a breakpoint is easy - just click on the line number in the left margin. Click again to make the breakpoint go away. Stop your debugger if it's running, and set a breakpoint on line 60:

Windows > Debugging > Breakpoints, or Alt-Shift-5 if your Breakpoints tab doesn't show up.

Some important things to know about breakpoints:

Now start the debugger. The program should halt, the output tab should say:

Launching

Initializing simulator

User program running

Breakpoint hit at line 60 in file C:/ece3724/pic24_code_examples/chap03/mptst_byte.s.

User program stopped

And if we look at the Watches window, you should see...

The green arrow (currently on top of the breakpoint) shows the location of the program counter.

...a bunch of nothing. That's because this is the first line of code, and as mentioned earlier, it hasn't executed yet. If you click on File Registers to view the contents of data memory, you can see that, indeed, the registers (at 0x0000) and the variables (at 0x1000) are all zeroes. (Except for W15, which is the stack pointer - don't mess with this). Slightly more interestingly, if you click on Program Memory, you can see the line of assembly that's about to execute:

Remember, right-click and select Symbolic Mode and Verbose Labels.

The program counter (green arrow) indicates the location in program memory that is about to execute, and as might be expected, it's the same assembly instruction as the line in the program (0x64 = 100). Notice the __reset label. Scroll up to the top of program memory and you will see a GOTO __reset, which is how we got here, as program execution always begins at 0x0000

After we've paused at a breakpoint, we can step through the program line-by-line and examine:

To do this, we use the debugger commands:

These commands can also be accessed through the Debug menu, but you never will. In fact, you also probably will not want to click the icons dozens of times, so you need to learn the hotkeys, or at least the most important one (especially if you want to get all your prelab points).

F7 - Step Into - executes a single line of the program

F8 - Step Over - executes a single line of the program, but skips past whole functions (does the same thing as Step Into here since there are no functions to get into, and will also get you prelab credit).

F5 (unless you messed around with your shortcut keys like I did) - Continue  - This is the green play button. It resumes execution of the program and goes on to the end (or until you hit another breakpoint).

You can learn about all the debug commands here if you're curious, but you'll probably never use the other ones. Just take a moment to play around with these three and marvel at how the contents of the registers and variables change as each line of code executes.

PIC24 Assembly

In order to complete this lab, you'll need to know some assembly. Besides the ebook and lecture slides, the required information can be found in the PIC24 Assembly Primer. (Just the first half, up to where it says "YOU NEED TO KNOW THIS MUCH ASSEMBLY TO DO LAB 2" in bright red)

Code commenting and neatness

Proper commenting and neat, organized code is more important than writing correct assembly code (except on the exams). You may never program assembly again in your life after you take this class, but you will almost certainly be required to write code that your employers, coworkers, and/or subordinates can understand. For the assembly labs (2-5), since most of what you are translating is just random math code in C, you are not expected to write "traditional" comments like:

; move register contents to variables and increment counter

or

; this shifts W2 left by 3 bits, then adds #0x3423 to W1

(Though you can if you want to and won't be penalized - use whatever additional comments you want that help you write the program.) 

You are expected to:

Prelab (20 points)

Before the TA arrives:

TA checkoff

With the TA watching:

Task 1: mptst_word.s (20)

For this task, you perform some simple calculations with the last four digits of your student ID number, then observe that the proper result is stored in data memory.

Be sure that only the mptst_word project is open. Stop the debugger. Open mptst_word.s.

DELETE THIS.

2. Put the proper header in its place:

+1 to your lab grade if you fix the spelling error from 2013.

3. Also erase these two lines, which are relics from the ebook:

4. Modify the i = 2047 assignment to be the last four digits of your student ID (the one on your student ID card, not your NetID from your email address). This is the only line of code you have to change for this task. Literally four numbers. Note: In all tasks, if your number begins with a 0, omit it, or the program will give odd results, as a prefix of 0 indicates an octal number. So if your number is #0123, just use #123.

On this and all other labs, including the practicum, do not use the wrong number or you will not get credit for the task.

For example if my student ID ended in 7777, I would do this.

5. Debug project

6. Read the section entitled "Screenshots" at the bottom of the page. Then, take a screenshot of the Watch window contents (showing  u16_i, u16_j, u16_k, and WREG0, WREG1, WREG2). 

7. Take a screenshot of the data memory (File Registers window contents showing the variables). Be sure that u16_k is showing, as this is the "answer" variable that we care about. 

8. Fix the comment above the line you changed to have your student ID in it.

9. Fix the comments for the C code at the top of the file.

Checkoff: 

Task 2: netid.s (40 points)

In this task, you'll write a program in PIC24 assembly to perform some calculations, then use MPLAB to observe data memory and verify that your answer is correct.

2. Name the file netid and click Finish.

3. Go back to your mptst_word.s file, hit Ctrl-A to select everything. Hit Ctrl-C to copy, go back to the blank netid.s file you just created, and hit Ctrl-V to paste everything in.

4. Close your mptst_word.s file. Right click on mptst_word.s (the file not the project) in the Projects window, and select "Exclude file(s) from current configuration".

5. Debug the project again, just to check that it's working.

6. Fix the header, changing the filename in two (2) places to netid.s.

7. Here's the C code you're going to translate:

uint16_t u16_netid;

uint16_t u16_studentid;

uint16_t u16_answer;


u16_netid = __; // numbers from net ID (decimal)

u16_studentid = ____; // last four of student ID (decimal)


u16_studentid -= u16_netid;

u16_studentid = u16_studentid & 0xB0B0;

u16_studentid = u16_studentid | 0xC0C0;

u16_studentid = u16_studentid ^ u16_netid;

u16_studentid = ~u16_studentid;

u16_netid = u16_studentid << 3;

u16_studentid = u16_netid >> 2;

u16_answer = u16_studentid + u16_netid;

Copy-paste it into netid.s, overwriting the old C code at the top of the file. Make each line a comment by preceding it with a semicolon:

8. Type the the last 4 of your student ID and the numbers from your net ID (email address) into the blanks.

9. Declare your variables. Luckily, there were three 16-bit variables in mptst_word, so all you have to do is change their names. Leave the fourth variable, u16_bug alone. MPLAB has a bug where it shows the wrong size for the last variable you declare. Microchip will probably fix this bug by 2014, but for now a workaround is to declare a dummy variable that we don't care about:

I changed the first variable. +1 to your Lab 2 grade if you correct the comment over u16_bug like I did here.

10. Now the actual task: You must translate each line of the C program to assembly instruction(s). Some hints/guidelines:

Fine.

Also fine.

Not fine.

; W0---------W1

; u16_j += u16_k;

add u16j, w1, whatever


; W2 -------- W3 --- W4

; u16_sum + etc...

11. Use the Watches window to watch variables u16_netid, u16_studentid, and u16_answer as well as the registers you use. Delete the watches of variables you were watching before and any registers you're not using. Also, use the File Registers window to monitor the memory locations corresponding to these variables.

12. Debug your program. Take a screenshot of the Watch window contents. Take a screenshot of the the data memory showing u16_answer (File Registers window).

Checkoff: You have the correct value in u16_answer.

Report

See Lab Policy Summary for formatting guidance and a sample report.

How to Verify

You need to do the calculations by hand to show the grader that the answer in your screenshots are correct.

For example, let's say the C code you were translating was: 

u16_studentid = 2047;

u16_studentid++;

u16_studentid = u16_studentid << 1;

Satisfactory verification

u16_studentid is the last four digits of my student ID, 2047. First, we increment by 1, giving 2048. Then left shift by 1 bit.

2048 = 0x800 = 0000 1000 0000 0000

Left shift 1 gives 0001 0000 0000 0000 or 0x1000

The screenshots below of the data memory and the Watches window show that u16_studentid contains 0x1000

Unsatisfactory verification

2047+1=0x8000

left shift 1 =4096 see screenshots

Grading

If you do not successfully complete a task and your report fails to mention or glosses over this fact, you will receive a zero for the report portion of your grade as well as for the task. If you attempt to deceive the grader, e.g. by including screenshots not generated by the code you submitted, your instructor will be notified and you will be recommended for an Honor Code violation.

The report is worth 20 points for neatly and coherently presenting your information to a reader. The following non-exhaustive list of errors will result in losing credit from the report portion of the lab grade:

The tasks are worth 60 points. If your report indicates that you did not successfully complete or do not understand a task, you will lose credit, even if you performed it during the lab. The same is true for tasks performed during the prelab. There are two tasks. The first task is worth 20 points. The second task is worth 40 points. The following non-exhaustive list of errors will result in losing credit from a task:

Lab reports that flagrantly violate submission policy (wrong lab, no screenshots, no title page, no text besides headings/labels, mostly blank, assembly code pasted into pdf, paragraphs of lab text pasted in, extremely sloppy/unprofessional, missing code etc.) will not be accepted. You will receive a zero for the lab and may resubmit with late penalty.

Screenshots

When taking screenshots, use a snipping tool for screen capture. Don't select the entire screen or most of it.

Too much screen.

But don't zoom in so much that you're missing important information. Leave some surroundings, such as labels, headings, addresses, to give your image meaning.

Not enough screen.

Good.

Good.

If you resize the image in your report, be sure to preserve aspect ratio. (In Word, hold down the Shift key)

Hard to read.

If you're taking screenshots of the Watches Window, adjust the size of the columns to make them fit nicely. Also, do not highlight one of the watches as the dark blue makes them hard to read:

I found this article, How to Change Default Action on PrtScrn Button in Windows 11 from askdavetaylor.com to be helpful.