03 November 2011

Tutorial 16e: Programming the Flash Memory

When we call the calibration values CALDCO_1MHZ and CALBC1_1MHZ in the code for our MSP430, those values refer to the address in SegmentA where the values are stored. They're not located in a place that's easy to find, however; they're stored in the linker command file, specific to each device. (If you're curious, take a look at the file in ${base dir}/Texas Instruments/ccsv4/msp430/include/msp430g2231.cmd, where your base directory is wherever you've installed CCS (likely in C:\Program Files for Windows). Be careful not to change anything in this file, though; this file is essential for proper programming of the G2231 device, as each is to their respective devices.) We could make a copy of this file and use it in our linker when we program the MSP430, but that requires a number of steps that are difficult to remember. All we really need is a way to tell our program to look at the specific address where we've saved the calibration values for our UART. All we really need is a pointer.

Pointers
We've not dealt with pointers up to this tutorial, but they're not really a difficult concept. Let's say we have code that declares the following two items:
   int var;
   int *ptr;
The first is what we're used to seeing; we declare a variable of type int (16 bits in MSP430), which will store a signed integer value. The second is also a declaration of type int, but rather than a variable, it is a pointer. The stored number in ptr doesn't refer to the value of a variable, but rather the address where a variable of type int is stored. (The actual size of the pointer in an MSP430 is 16 bits, so char *ptr; would also be a 16 bit value, even though it points to memory where an 8 bit value is being stored.)

In the C language, we have a way to refer to the address of a specific variable by using the & character. So from this point, if we assign ptr = &var; then ptr now points to the address where we've stored the int value var. Similarly, we can reference the value stored in a pointer with the * character. int var2 = *ptr; would store the value at address ptr in the new variable var2. If we want to assign a specific address to a pointer, rather than reference the address of a variable, we can use a literal of the form (int *)0x1234.

In the MSP430, an int variable takes 16 bits, while a char variable take 8. When we want to reference a specific word, we'll use a pointer of type int. If we want to reference a specific byte, such as the calibration values for the DCO, we'll use a pointer of type char. To use the DCO values we'll program in SegmentB, we can use the following:
    char *CALBC1_UART = (char *) 0x10BE;
    char *CALDCO_UART = (char *) 0x10BF;
or, if we'd rather not use extra memory, define in the header:
    #define  CALBC1_UART    *(char *) 0x10BE
    #define  CALDCO_UART    *(char *) 0x10BF

The Flash Memory Controller
Ok, now we've got a handle on how to reference portions of the flash memory. Now it's time to learn how to actually write to it. The MSP430 has a peripheral designed specifically to handle managing the flash memory called the Flash Memory Controller. Since it would be dangerous to manipulate the flash memory willy-nilly, it's set up like the Watchdog Timer, so that a key is needed to change any of its four control registers. The key value is 0xA5, conveniently provided in the header files as the value FWKEY. Here are the portions we'll need to know about:

FCTL1

  • FWKEY (bits 15-8):  The key is read as the value 0x96. Each register has this.
  • BLKWRT (bit 7): control bit for block write mode. We will be writing word by word, so we'll save this function for a future tutorial.
  • WRT (bit 6): write mode enable. Before we can write to any flash segment, this bit must be enabled.
  • MERAS & ERASE (bits 2 and 1): Control the mode of erasure. You can erase a single segment, the entire main memory, or the main memory and information segments both. (Depending on whether SegA is unlocked.)
FCTL2
  • FSSELx (bits 7-6): These bits select which clock source to use for the programming.
  • FNx (bits 5-0): These bits allow you to divide the source clock by any factor up to 64. (Divide by FNx + 1)
FCTL3
  • FAIL (bit 7): We don't want to see this bit set! For our purposes, it could mean the clock source has failed for some reason. If this happens, it needs to be reset by software before anything else can be done.
  • LOCKA (bit 6): I won't go into how this works; this bit controls whether SegA can be erased/written. If you find you absolutely must change something in this segment, you can read in the Family User's Guide to learn how to use this bit.
  • LOCK (bit 4): When this bit is set, the flash memory is completely locked, and cannot be erased or written.
  • WAIT (bit 3): Indicates when the flash memory is being erased or written.
FCTL4
  • This register is not available on all devices; it controls the 'marginal read mode'. We won't be using it here.
To do a successful programming of the Information Segment, we first set the clock for the controller. The actual frequency isn't terribly important, as long as it falls between 257 and 476 kHz. The default DCO setting of the MSP430 is about 1.1 MHz, and so a division of 3 (FNx = 2) works well, giving us roughly 370 kHz. We'll calibrate the DCO to 7.3728 MHz, so a division of 20 (FNx = 19) will give us about the same.

If we have anything we want to save in the segment, then the entire contents would need to be saved to a buffer. Likely, your SegB is blank, so we'll just proceed forward. Next, we set the controller to erase mode. We don't want to erase the main memory segments, so we only need the ERASE bit. We then clear the LOCK bit to allow changing the flash memory. When the controller is configured this way, we initiate the erase cycle by writing to any address within the segment. There's nothing magic about what value we write, but it is absolutely crucial that you have your address pointer pointing to somewhere in the segment you actually want to erase!

Once it has erased, we reconfigure the controller to write mode (not block write), and then proceed to write the values we need, either as bytes or words. If you preserved the prior contents, a better method is to change the contents to the new values and use block write mode. For this tutorial, we'll keep it simple.

Finally, when everything is written, we clean up, clearing the write mode bit and locking the flash memory.


The code I wrote for writing the UART DCO calibration to Segment B using the TLV format is found in uartcalG2231.c. Remember, if you run this, it requires the watch crystal. If there is anything already stored in SegB, it will be lost. If you'd rather store it in Segment C (0x1040 to 0x107F) or Segment D (0x1000 to 0x103F), change the address in the assignment instructions accordingly. If you choose to put in in Segment A (0x10C0 to 0x10FF), look in the Family User's Guide for instructions on unlocking the Segment. I do not recommend this, however, since we're calibrating a non-standard DCO frequency. Wherever you choose to store it, you'll need to remember the address. If you use my method here, that address is 0x10BE for the CALBC1 value and 0x10BF for the CALDCO value. Next time we'll write code that pulls these calibration values from memory and configures the DCO and TimerA to start setting up our software UART.


This tool will be very useful to you; keep in mind that though the Value Line devices only have one DCO calibration and don't appear to have any calibrations for the ADC, there is space for them! This process is not too difficult, you can upgrade your devices to have better calibrations, essential for accurate scientific work. For more information on the ADC calibration values that are often included in MSP430 devices, see the TLV chapter of the Family User's Guide.

02 November 2011

Tutorial 16d: Flash Memory and TLV

I've used a number of resources in preparing this tutorial; in addition to the Family User's Guide and the device datasheets, one of the most helpful was an application report titled MSP430 Flash Memory Characteristics.

We'd really like to hold onto our DCO calibration for two reasons. We'd like to be able to use it later, but we'd also like to do so without using up our limited code space with self-calibration. In addition, we may need it in an application where we don't have a crystal connected to the device. (Rather, we could program the calibrations in our LaunchPad with a crystal connected, and then transfer the chip to our intended application while retaining the calibration values in memory.) Programming the flash memory in the MSP430 is not difficult, but there are a few things that have to be done properly to protect your device. The steps done in programming make more sense when we understand how flash memory works.

The Science in Flash
A NOR flash bit is a transistor with a little pocket for storing charge.
The flash memory inside the MSP430 is what we call NOR flash (as opposed to the NAND flash that makes up your typical USB flash drive, for example). It works by trapping charge in an isolated region called a floating gate. The charge in the floating gate changes the transistor's threshold, and determines what value is read from the bit. Acting much like a switch, a positive charge in the floating gate makes it so the read voltage "closes" the switch, and we read a logic 1. A negative charge keeps the switch open, and we read a logic 0.

When we erase flash memory, each bit is put in a state where the floating gate is positively charged. Thus, a "blank" bit will always read 1; a byte of erased flash will read 0xFF. We can program the bit to a 0 by applying a high voltage to the control gate, which allows the floating gate to push charges through the drain. The resulting negative charge in the floating gate is retained, barring physical effects like quantum tunneling that take 100's of years to de-program the bit. (At 25°C, the typical lifetime of a NOR flash bit is on the order of 1,000 years!) Fortunately, the ability to generate this high voltage is built into the Flash Controller peripheral of the MSP430, so we are able to program the flash memory as long as the operating voltage on our microcontroller is at least 2.2 V.

The flash memory in the MSP430 is organized in chunks called segments. The Main Memory portion is divided into segments of 512 bytes. (That means there are 4 segments in the main memory of both the G2211 and G2231, which each have 2 kB available.) Each segment is further subdivided into blocks of 64 bytes. Additionally, an extra 512 bytes is included in each MSP430 device, divided into segments of either 64 or 128 bytes (one or two blocks, respectively). These segments make up the Information Memory portion of the device. The Value Line devices that come with the LaunchPad have four information memory segments of 64 bytes each, called Segment A–D.

The physical structure of the flash cells is important to us, as it has direct bearing on how we deal with it. First of all, when we erase flash memory, we can only erase an entire segment at a time! This means any time we need to change a 0 in a single cell to a 1, every cell in the segment has to be erased. When we program flash memory, the high voltage is applied across an entire block at a time, even if we are only programming one cell. This voltage causes stress to the flash cells, and so we cannot exceed a specified "cumulative programming time", typically 10 ms. Erasing releases the stress, and essentially resets our cumulative timer to 0. These stipulations affect our programming speeds and how often the block needs to be erased.

At the typical speeds we can use (between 257 and 476 kHz), we can program an entire block twice. (Note that in this case, "program" doesn't mean we can write any value-- we can change 1's to 0's twice. To change 0's to 1's, we are forced to erase the entire segment.) We cannot, however, program the same byte multiple times, even if we don't program any other bytes in the block. The rule of thumb, then, is if you reach 10 ms of programming time or write to the same byte twice, the block (and thus the entire segment for main memory) must be erased. This is a real pain, especially if we want to use main memory to store our calibrations. Because of this, I would recommend using the Information segments for storing anything you want to retain outside of the actual program in the device. The process you would use would be to read the entire contents of the block to a buffer (in RAM), erase the Information Segment, change anything necessary in the buffer value, and re-write the buffer to the segment. (It seems like a lot more to do than you're used to when using a flash drive, but in reality the same thing is happening there. Your computer just does a fantastic job of hiding it so you don't have to worry about it.)

Information Memory
A quick word about the various segments: segments B–D are each alike in dignity. However, SegmentA is set aside specifically by TI to store information that should be retained regardless of any programming changes. The factory calibrations, for example, are stored in this segment. As a result, this segment is locked, and you will have to set a particular bit before any instructions erasing or programming within this segment. In addition, to ensure integrity of the data stored in SegA, one word (two bytes) of it is set aside as a checksum, which I'll explain shortly. If you change anything in the segment, a checksum calculation will fail. Some programs rely on this, so if you really must change something in this segment, be prepared to deal with the consequences. Well, at least be prepared to recalculate what the checksum value will be. For our purposes in this tutorial, we'll use SegmentB instead, but we will program it in much the same way that SegmentA is structured. That way, if you choose, you can use SegA to store your calibrations, since that is where they are intended to be.

Memory Save
Button
Let's take a look at how SegA is put together. Fire up the debugger in CCS; it doesn't matter what code you're using, as we won't even be running the program. We just want to enter the debug mode. Once there, the default view has a panel on the right side with tabs for the code disassembly and memory; the memory tab shows the contents of the flash memory of the device. (If this window is not visible for you, you can find it by selecting Window → Show View → Memory.) The information memory is located (as specified in the datasheet) from address 0x1000 to 0x10FF. SegA starts at 0x10C0 and ends at 0x10FF. You can use this window to browse that region, or you can save a particular region of memory to a text file. To do this, click the save button, navigate to a file you want to save the data to, and enter a Start Address of 0x10C0 and a length of 0x20. (Note it specifies to give the length in words; a word is 16 bits in the MSP430, so there are 0x20 (32) words in the 64-byte segment.)

An example of the output from my G2231 device is here. The first line specifies where in the memory the dump comes from. The first line has one word–it comes from the two bytes at addresses 0x10C0 and 0x10C1. Take note that the lower address of the word refers to the least significant byte (LSB, as opposed to lower case lsb for least significant bit), while the higher address refers to the most significant byte (MSB). The last line has the 32nd word–from addresses 0x10FE (LSB) and 0x10FF (MSB). Most of the memory in SegA is obviously blank, as most of the entries are 0xFFFF. (Remember, when flash is erased it reads logic 1.) There are a few programmed words, however, so let's see what each one means. In the x2xx Family User's Guide (current revision as of this writing is slau144h), turn to the chapter on TLV, chapter 24. TLV stands for Tag-Length-Value. This is the format TI uses in SegA to store information. Basically, one word is dedicated to specifying the length of memory allocated to a specific type of data and what type of data is stored there. Table 24-1 gives an example of how this is done. The first word in the segment stores a checksum value. Note that it specifies the checksum as the two's complement of the bitwise XOR. If you start with the next word and XOR it with the third word, that result with the fourth word, and so on, then add it to the checksum value, it will add up to zero. Something like this:


int chksum = 0;
char passed;
int *i;
for (i=(int *)0x10C2; i<(int *)0x1100; i++) {
    chksum ^= *i;
}
if (chksum + *(int *)0x10C0 == 0)
    passed = 1;
else
    passed = 0;


Note: I'm not completely familiar with pointers just yet; I'm working that out in preparation for the next tutorial. If there's an error in this code, I'll correct it then. For now, think of it more as pseudocode.


Now that we understand how the segment memory is organized, let's look at what's inside it. Using my device, I have a checksum value of 0xB22C. The next word is 0x26FE. This means that the next 0x26 entries (38 bytes) are of type 0xFE. Looking in Table 24-2, we see that 0xFE refers to "TAG_EMPTY", meaning the next 38 bytes (or 19 words) are unused. Sure enough, the next 19 lines are all 0xFFFF. The next line gives the next Tag-Length entry: 0x1010. The next 0x10 entries (16 bytes or 8 words) are of type 0x10, which isn't specified in the Family User's Guide. I've submitted a question to TI support to find out about this. In any case, each entry is blank. The next Tag-Length listed is 0x0201, which means there's one word of type "TAG_DCO_30". Here we have the DCO calibration values at room temperature and 3 V. (Note that the Vcc value of the LaunchPad itself is 3.3 V, and remember that different voltage has a significant impact on the DCO!) There's only one entry, which we know has the values for CALBC1_1MHZ (0x86 on mine) and CALDCO_1MHZ (0xC4 on mine) as per the G2231 datasheet.


Reader Exercise: Using either your memory dump or mine, calculate the checksum of SegA and compare it to the value at address 0x10C0. Hint: xor'ing 0xFFFF twice has no effect; an even number of these lines can be ignored. When added to the stored checksum value, do you get zero? Calculate the two's complement by ~chksum + 1 and compare it to the stored value.


Preparing the Custom DCO Calibration
Here's the plan for our code: we'll find a custom calibration value for 7.3278 MHz and store it in SegB using the standard TLV coding set by TI. (You could do this in SegA if you wish, but since we're using a non-standard DCO frequency, I've opted to keep it out for now.) SegB is found in the memory range 0x1080 to 0x10BF. The organization of what we'll be writing will then be like this:
There's a typo here.. should be 0x38FE. I will fix the image soon.


We use the crystal to find the calibration value for 7.3278 MHz. This value is put into the above table to calculate the checksum: 
chksum = 0x38FE ^ 0x0201 ^ {calibration values}
       = 0x3AFF ^ {calibration values}
The value stored at 0x1080 is then ~chksum + 1.


Next, we erase SegB, and write in the following addresses:

  • 0x1080: two's complement of chksum
  • 0x1082: 0x37FE
  • 0x10BC: 0x0201
  • 0x10BE: 0x{CALBC1}{CALDCO}
This tutorial has ended up pretty long, so we'll end the discussion here. The next tutorial will review the registers in the MSP430 Flash Memory controller and describe how to program this information to the Information Memory.

Reader Exercise: The Value Line devices do not come with the other standard calibrations: 8 MHz, 12 MHz, and 16 MHz. In the chapter on TLV of the Family User's Guide, we see that the locations of these calibrations are standardized for SegA to appear in the order TLV Tag, CAL_16MHz, CAL_12MHz, CAL_8MHz, CAL_1MHz. The data in SegA for the Value Line devices doesn't leave room for these with the other three calibrations left blank, so the entire segment structure needs to be shifted. If we want to add these without loosing any of the remaining structure, how will the segment be set up? Draw up a table similar to that used in this tutorial to map out the segment structure, and show how to calculate the new checksum value based on this table.