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.