EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Problem writing flash memory.

Started by baxtercodeworks March 21, 2007
Background: I'm using a MSP430F1121a with a 3.6864MHz crystal.
Program using IAR Kickstart.

note: I've tried several things with similar results, this is the
simplified version

---

I want to write a string to flash memory that can be changed. I
created the following function:
//-----

const unsigned char * INFOMEM = (unsigned char *) 0x1000;
void WritePID(char ch, int offset)
{
unsigned char * dest; // = (unsigned char*)pidStr;
dest = (unsigned char *) INFOMEM;

_DINT();
FCTL2 = FWKEY + FSSEL_1 + FN0 + FN1; // Select MCLK/3 (1.04MHz / 3)

FCTL3 = FWKEY; // Unlock flash memory
FCTL1 = FWKEY + WRT; // Set write mode
dest[offset] = ch;
while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK; // Lock flash memory
_EINT();
}

//-----

The first time I call this function, it works perfectly. Memory shows
the exact string I wrote and I can retrieve it with no problem. Any
time I try to change it, it produces garbage - I may see one or two
characters that I wrote, but it will throw in puntuation, spaces,
random chars, etc.

Can anybody suggest what I'm doing wrong - or not doing that I need to do?

Beginning Microcontrollers with the MSP430

Oops! Code should be:
---
const unsigned char * INFOMEM = (unsigned char *) 0x1000;

void WritePIDStr(const char* data)
{
unsigned char * dest;
dest = (unsigned char *) INFOMEM;

_DINT();
FCTL2 = FWKEY + FSSEL_1 + FN0 + FN1; // Select MCLK/3 (1.04MHz / 3)
//FCTL2 = FWKEY + FSSEL_1 + FN3;

FCTL3 = FWKEY; // Unlock flash memory
FCTL1 = FWKEY + WRT; // Set write mode
while (*data) {
unsigned char ch = *data;
*dest = ch;
while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
++dest;
++data;
}
*dest = 0;
while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK; // Lock flash memory
_EINT();
}
--- In m..., "baxtercodeworks" wrote:
>
> Background: I'm using a MSP430F1121a with a 3.6864MHz crystal.
> Program using IAR Kickstart.
>
> note: I've tried several things with similar results, this is the
> simplified version
>
> ---
>
> I want to write a string to flash memory that can be changed. I
> created the following function:
>
//-----
>
> const unsigned char * INFOMEM = (unsigned char *) 0x1000;
> void WritePID(char ch, int offset)
> {
> unsigned char * dest; // = (unsigned char*)pidStr;
> dest = (unsigned char *) INFOMEM;
>
> _DINT();
> FCTL2 = FWKEY + FSSEL_1 + FN0 + FN1; // Select MCLK/3 (1.04MHz / 3)
>
> FCTL3 = FWKEY; // Unlock flash memory
> FCTL1 = FWKEY + WRT; // Set write mode
> dest[offset] = ch;
> while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
> FCTL1 = FWKEY;
> FCTL3 = FWKEY + LOCK; // Lock flash memory
> _EINT();
> }
//-----
>
> The first time I call this function, it works perfectly. Memory shows
> the exact string I wrote and I can retrieve it with no problem. Any
> time I try to change it, it produces garbage - I may see one or two
> characters that I wrote, but it will throw in puntuation, spaces,
> random chars, etc.
>
> Can anybody suggest what I'm doing wrong - or not doing that I need
to do?
>
User's Guide has flow-chart and assembly code example. Try follow
them!
(on page 5-9 of slau049f.pdf)

--- In m..., "baxtercodeworks" wrote:
>
> Oops! Code should be:
> ---
> const unsigned char * INFOMEM = (unsigned char *) 0x1000;
>
> void WritePIDStr(const char* data)
> {
> unsigned char * dest;
> dest = (unsigned char *) INFOMEM;
>
> _DINT();
> FCTL2 = FWKEY + FSSEL_1 + FN0 + FN1; // Select MCLK/3
(1.04MHz / 3)
> //FCTL2 = FWKEY + FSSEL_1 + FN3;
>
> FCTL3 = FWKEY; // Unlock flash memory
> FCTL1 = FWKEY + WRT; // Set write mode
> while (*data) {
> unsigned char ch = *data;
> *dest = ch;
> while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
> ++dest;
> ++data;
> }
> *dest = 0;
> while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
> FCTL1 = FWKEY;
> FCTL3 = FWKEY + LOCK; // Lock flash memory
> _EINT();
> }
> --- In m..., "baxtercodeworks" wrote:
> >
> > Background: I'm using a MSP430F1121a with a 3.6864MHz crystal.
> > Program using IAR Kickstart.
> >
> > note: I've tried several things with similar results, this is the
> > simplified version
> >
> > ---
> >
> > I want to write a string to flash memory that can be changed. I
> > created the following function:
> >
> >
> >
> //------------------------------
-----------
> >
> > const unsigned char * INFOMEM = (unsigned char *) 0x1000;
> > void WritePID(char ch, int offset)
> > {
> > unsigned char * dest; // = (unsigned char*)pidStr;
> > dest = (unsigned char *) INFOMEM;
> >
> > _DINT();
> > FCTL2 = FWKEY + FSSEL_1 + FN0 + FN1; // Select MCLK/3
(1.04MHz / 3)
> >
> > FCTL3 = FWKEY; // Unlock flash memory
> > FCTL1 = FWKEY + WRT; // Set write mode
> > dest[offset] = ch;
> > while((FCTL3 & WAIT) != WAIT); // Wait for write to complete
> > FCTL1 = FWKEY;
> > FCTL3 = FWKEY + LOCK; // Lock flash memory
> > _EINT();
> > }
> >
> >
> //------------------------------
-----------
> >
> > The first time I call this function, it works perfectly. Memory
shows
> > the exact string I wrote and I can retrieve it with no problem.
Any
> > time I try to change it, it produces garbage - I may see one or
two
> > characters that I wrote, but it will throw in puntuation, spaces,
> > random chars, etc.
> >
> > Can anybody suggest what I'm doing wrong - or not doing that I
need
> to do?
>
Nope. No cigar. One of my sources for the code I posted was
slau049c.pdf - not exact, but close enough.

After I posted, though, I had a wild idea and figured out the problem:
the flash memory has to be erased (which actually sets it to 0xff) in
order to be re-written. Turns out you don't actually put a value in a
flash memory location - it just turns certain bits off. I did find an
oblique reference to this in the Nagy book in the section on flash memory.
--- In m..., "old_cow_yellow"
wrote:
>
> User's Guide has flow-chart and assembly code example. Try follow
> them!
> (on page 5-9 of slau049f.pdf)
>

The 2024 Embedded Online Conference