EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Flash Block Write doesn't work?

Started by Ralph Preston November 20, 2006
Hello all,

I'm working on an msp430f1611, so far can write bytes, and erase segments in
the flash, but I can't block write. I've implemented the algorithm on page
5-12 of the msp430UserGuide.pdf, but it ain't workin; only the first byte is
ever written. Are there any known problems, or deviations from the
documentation? I've checked the archives but didn't find anything.

"Initiating a Byte/Word Write from RAM" on page 5-10 works fine, however I
don't want to use it to write 64 bytes because the cumulative programming
time would exceed 4ms, the tCPT of the part. An alternative is to write
only words (not bytes), requiring only 32 writes per block, so the tCPT
would be below 4ms. But it's bugging me that I can't get Block Writes
working, any help is appreciated. Code is below.

The details:
MCLK = ~3.57 MHz
SMCLK = ~382 kHz // confirmed via scope
FCTL2
FSSELx = 11 SMCLK
FNx = 0

This is my write bytes routing (essentiall), which does work:

uint Write_Bytes(uchar* start_addr, uint length, uchar* buf) {
Int I;

// FCTL2 is already configured
DISABLE_INTERRUPTS;
While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
CLEAR_LOCK; // FCTL3 = FWKEY
ENABLE_WRITE; // FCTL1 = FWKEY+WRT

For(I=0; I *(start_addr+I) = *(buf+I);
}

While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
DISABLE_WRITE; // FCTL1 = FWKEY
SET_LOCK; // FCTL3 = FWKEY+LOCK
ENABLE_INTERRUPTS;

Return I;
}

The following Write Block doesn't work. I've tried variations but whenever
I set FCTL1 = FWKEY+BLKWRT+WRT only the first byte is written.

uint Write_Block(uchar* start_addr, uint length, uchar* buf) {
Int I;

// FCTL2 is already configured
DISABLE_INTERRUPTS;
While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
CLEAR_LOCK; // FCTL3 = FWKEY
ENABLE_BLOCK_WRITE; // FCTL1 = FWKEY+BLKWRT+WRT

For(I=0; I *(start_addr+I) = *(buf+I);

While(FLASH_WAIT == 0) // FCTL3 & WAIT
{; // busy wait
}
if(block_border(start_addr+I) == TRUE) {
DISABLE_BLOCK_WRITE; // FCTL2 = FWKEY+WRT
while(FLASH_BUSY) {;}
if(I+1 ENABLE_BLOCK_WRITE;
}
}
}

DISABLE_BLOCK_WRITE; // FCTL2 = FWKEY+WRT

While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}

DISABLE_WRITE; // FCTL1 = FWKEY
SET_LOCK; // FCTL3 = FWKEY+LOCK
ENABLE_INTERRUPTS;

Return I;
}

Thanks in advance,

Ralph A. Preston
The MITRE Corporation
202 Burlington Road MS E095
Bedford, MA 01730
http://www.mitre.org

Beginning Microcontrollers with the MSP430

Just a (wild) guess, but assuming you are running your code from RAM
(which is required in order to do block writes) have a look at the
assembler output of the compiler. Check that no library math
functions (in Flash) are being called. Also block_border(() isn't
shown, but it too (and any lower functions) must reside in RAM.

Hugh

At 11:44 AM 11/16/2006, you wrote:
Hello all,

I'm working on an msp430f1611, so far can write bytes, and erase segments in
the flash, but I can't block write. I've implemented the algorithm on page
5-12 of the msp430UserGuide.pdf, but it ain't workin; only the first byte is
ever written. Are there any known problems, or deviations from the
documentation? I've checked the archives but didn't find anything.

"Initiating a Byte/Word Write from RAM" on page 5-10 works fine, however I
don't want to use it to write 64 bytes because the cumulative programming
time would exceed 4ms, the tCPT of the part. An alternative is to write
only words (not bytes), requiring only 32 writes per block, so the tCPT
would be below 4ms. But it's bugging me that I can't get Block Writes
working, any help is appreciated. Code is below.

The details:
MCLK = ~3.57 MHz
SMCLK = ~382 kHz // confirmed via scope
FCTL2
FSSELx = 11 SMCLK
FNx = 0

This is my write bytes routing (essentiall), which does work:

uint Write_Bytes(uchar* start_addr, uint length, uchar* buf) {
Int I;

// FCTL2 is already configured
DISABLE_INTERRUPTS;
While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
CLEAR_LOCK; // FCTL3 = FWKEY
ENABLE_WRITE; // FCTL1 = FWKEY+WRT

For(I=0; I *(start_addr+I) = *(buf+I);
}

While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
DISABLE_WRITE; // FCTL1 = FWKEY
SET_LOCK; // FCTL3 = FWKEY+LOCK
ENABLE_INTERRUPTS;

Return I;
}

The following Write Block doesn't work. I've tried variations but whenever
I set FCTL1 = FWKEY+BLKWRT+WRT only the first byte is written.

uint Write_Block(uchar* start_addr, uint length, uchar* buf) {
Int I;

// FCTL2 is already configured
DISABLE_INTERRUPTS;
While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}
CLEAR_LOCK; // FCTL3 = FWKEY
ENABLE_BLOCK_WRITE; // FCTL1 = FWKEY+BLKWRT+WRT

For(I=0; I *(start_addr+I) = *(buf+I);

While(FLASH_WAIT == 0) // FCTL3 & WAIT
{; // busy wait
}
if(block_border(start_addr+I) == TRUE) {
DISABLE_BLOCK_WRITE; // FCTL2 = FWKEY+WRT
while(FLASH_BUSY) {;}
if(I+1 ENABLE_BLOCK_WRITE;
}
}
}

DISABLE_BLOCK_WRITE; // FCTL2 = FWKEY+WRT

While(FLASH_BUSY) // (FCTL3 & BUSY)
{; // busy wait
}

DISABLE_WRITE; // FCTL1 = FWKEY
SET_LOCK; // FCTL3 = FWKEY+LOCK
ENABLE_INTERRUPTS;

Return I;
}

Thanks in advance,

Ralph A. Preston
The MITRE Corporation
202 Burlington Road MS E095
Bedford, MA 01730
http://www.mitre.org

Memfault Beyond the Launch