CST 337 Lab 4 -- Memory Allocation and Initialization

In this lab, we will examine some of the issues related to memory allocation and initialization in the PIC32 and C. We will only need to use the simulator for this project.

The Lab

1) Start a new project, and enter the following code (note that you should be able to "cut and paste"):

// Memory Allocation and Initialization Test

#include <xc.h>
#include <string.h>

const char a[] = "CST 337 Lab 4";
char b[] =       "Initialized Global Var";
const char c[] = "Initialized Constant String";
char d[100] =    "Initialized String Array";
unsigned int gc = 0; //global initialized to 0
unsigned int gd; //global uninitialized
unsigned int ge = 0x45; //global initialized to 0x45

int main(void)
{
unsigned int ic = 0x0F1E2D3C;
unsigned int id = 1;
unsigned int ie;
const unsigned int icf = 0x98765432;
static unsigned int isf = 0x67452301;
static const unsigned int iscf = 0xABCDEFFE;

unsigned long long Lc = 0x4B5A69788796A5B4LL;
static const unsigned long long Lcc = 0xFEDCBA9876543210LL;
unsigned long long Ld = 1;
unsigned long long Le;

char la[] = "Local String Test";

ie = 0x19283746;
ic = icf;
ic = isf;
ic = iscf;
id = gc;

Le = 0x0123456789ABCDEFLL;
Le = Lcc;
Le = Lc;

strcpy(d,b); // Copy the b string into the d string
strcpy(d,a);
strcpy(d,c);
strcpy(b,c);
}

2) Build and (if necessary) debug the code. Open the Watch window and add the sp, fp and gp registers. (Note that the fp register is also known as s8). (Note that I have seen some debug sessions where the watch window wasn't updating registers properly. In this case, the "CPU Registers" target memory view will provide the values of fp, sp and gp). Then add all of the global and local variables defined in the code. To add the locals, the focus (i.e. the PC) will have to be inside the main routine, and past the point in the code where they are initialized.  (Set a breakpoint on the first strcpy call and run to that point then add the locals.)  Adding the globals and locals in the order they were declared will probably help with later steps, as will ensuring that the properties of the string symbols in the watch window is ASCII. Make sure the debugger is set to reset and debug startup at the reset vector (Tools > Options > Embedded > Reset @ > Reset Vector).  Next, open the Window > Target Memory Views > Data Memory window, right click on the data table and select "Fill Memory ..." to fill all of RAM (0x0000.0000 -- 0x0007.FFFC) with 0x55555555. (Also selecting "Keep Address Range" may save you some time later if you have to repeat this step.) Note that 0x55 is the ASCII code for "U".  Then, reset the device.

3)
4)
5) Use the "Step Into" key to step (about 13 times) while watching the the values of the sp and gp registers. The sp will change twice then the gp register will change twice.
6) Set a breakpoint on the opening brace at the beginning of main() (before any code is executed in main). Run to that point. (Open the disassembly window and verify that the breakpoint is on the first assembly instruction in main.)
7) Some of the local variables in main will no longer be "Invalid Address" or "Out of scope" in the watch window and some of them will already have their initial values.
Note that previous versions of the debugger did not report a local variable as being in scope until is was initialized, assigned or used the first time.  In MPLAB 6, all locals properly go in scope (no longer have an  invalid address) the moment main is entered.

8) Single step instructions in the main code window until some of the local variables addresses change to different addresses. What register being assigned a value caused these addresses to be changed? What is another name for this register? Why did changing its value change the addresses the debugger determines for these variables? (Look at the disassembly to see how ic (and others of these variables) are being referenced).
Skip this question. This actually works in MPLAB version 6.00, but in previous years the local variables did not get accurate addresses until after the frame pointer (fp or s8) was assigned since they are all referenced as offsets from the fp.

9) Check what addresses all of the non-static (also known as "automatic") local variables have. (Depending upon the version of the debugger, you may have to step past the instructions that use or initialize them in main to get their addresses to resolve (not "Invalid", blank or not show a register). 
10)
11)
12)
13) Set a breakpoint on the last strcpy() in the main program. Run to, then step over it while observing the global strings in the watch window.

14) Record the starting and ending addresses of main from the disassembly window.  (For the ending address, give the address of the nop following the jr ra at the end of main.)

15)  Examine the project's map file that is found in the project directory. Using the file explorer, navigate to the project's directory, then open the dist\default\debug directory. The project map file will have the .map extension. Open it with a suitable text editor. Scroll down to the "Microchip PIC32 Memory-Usage Report" section of the map file.
As a check, here is a list of the variables that need to appear in the tables: a, b, c, d, gc, gd, ge, isf, iscf, and Lcc. Also, show the addresses of the initializers for b, d, ge, and la.
It might be a good idea to show your tables to the professor before turning then in to make sure they are in the right format and have all the needed elements.

Data Ram
section variables
address






















Program Flash
section variables and initializers
address



























16) From their addresses, and from information found in tables 6.8 (Exception Vector Base Addresses) and 6.9 (Exception Vector Offsets) of MIPS Volume III (or see Lec 6 slides),

The Report

Include a print out of the final version of your code and the data and answers to all the questions posed in steps 3-16 (including the tables in step 15) above.  Submit this as a single pdf file in Canvas.