I am developing a program backup feature (in mspgcc) and I often need to transfer from backup to Program areas, etc.
I've been following the user guide's figure 7-12 flow diagram for block writing to flash. However, the first long word copy reads 0x3fff3fff from data_addr (which is wrong), writes it to flash_addr but the ACCVIFG get's triggered,disabling all the later memory writes.
I am running this from RAM as it is recommended in the manual.
Both interrupts and Watchdog are disabled.
Here are the data types used:
typedef uint8_t byte; typedef uint16_t word; typedef uint32_t long_word; #if __MSP430X__ typedef uint20_t address; #else typedef uint16_t address; #endif /*__MSP430X__*/
Here is my code for the operation (with the steps according to the mentioned flow):
i = IMAGE_APP_SIZE;
// 1. Test busy
while(FCTL3 & BUSY);
// 2. Clear Lock bit
FCTL3 = FWKEY;
while (i > 0){
j = WRITE_BLOCK_SIZE; //128-bytes row (block)
// 3. Enable block write mode
FCTL1 = FWKEY + BLKWRT + WRT;
while (j > 0){ //go through a block
// 4. write 4 bytes from data_addr (in flash)
flashWriteLongWord(flash_addr,
flashReadLongWord(data_addr));
// 5. Loop until WAIT is 1;
while(!(FCTL3 & WAIT));
flash_addr += long_word_size;
data_addr += long_word_size;
i -= long_word_size;
j -= long_word_size;
// 6. Block Border check.
}
// 7. Disable BLKWRT bit (BLKWRT = 0);
FCTL1 = FWKEY + WRT;
// 8. Loop until BUSY is 0;
while(FCTL3 & BUSY);
// 9. Another Block check.
}
//10. set WRT = 0, LOCK = 1
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
Here are the definitions of flashWriteLongWord and flashReadLongWord :
inline long_word flashReadLongWord(address flashAddr){
union {
long_word lw;
word w[2];
}result;
uint16_t register sr;
address register flash;
// save SR before disabling IRQ
__asm__ __volatile__ ( "mov r2,%0":"=r"(sr):);
__asm__ __volatile__ ( "movx.a %1, %0":"=r"(flash):"m"(flashAddr) );
__asm__ __volatile__ ( "movx.w 0(%1), %0":"=m"(result.w[0]):"r"(flash) );
__asm__ __volatile__ ( "movx.w 2(%1), %0":"=m"(result.w[1]):"r"(flash) );
// restore previous SR and IRQ state
__asm__ __volatile__ ( "mov %0,r2"::"r"(sr) );
return result.lw;
}
inline void flashWriteLongWord(address flashAddr, long_word l){
union{
word w[2];
long_word lw;
}lw;
uint16_t register sr;
address register flash; //address may be 16-32 bit depending the memory mode (small or large)
lw.lw = l;
// save SR before disabling IRQ
__asm__ __volatile__ ( "mov r2,%0":"=r"(sr):);
__asm__ __volatile__ ( "movx.a %1,%0":"=r"(flash):"m"(flashAddr) );
__asm__ __volatile__ ( "movx.w %1, 0(%0)":"=r"(flash):"m"(lw.w[0]) );
__asm__ __volatile__ ( "movx.w %1, 2(%0)":"=r"(flash):"m"(lw.w[1]) );
// restore previous SR and IRQ state
__asm__ __volatile__ ( "mov %0,r2"::"r"(sr) );
}
Is it because I am reading from flash while copying?
If so, where should I load to memory the 128-byte chunks? Between step 9 and 10?
Notice that the data_addr and flash_addr are from different banks.