This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F2013: Unexpected resets during I2C transfer after flash erase

Part Number: MSP430F2013

I have a custom bootloader communicating with the host using I2C and running in FC00-FFFF address space. I2C slave is interrupt driven. To program flash, an I2C command is send to erase the application space F800-FBFF. Before executing ERASE command the code verifies that the application space has non-0xFFFF words in it. If non-0xFFFF word is found, the sector is erased and the following sector is checked for non-0xFFF words. Since erasing is executed from ISR, I2C bus is released after the flash is erased thus preventing the host from sending the next command.

After the flash is erased and USIIFG flag is cleared releasing I2C bus, the host issues commands to program flash, 8 word (16 bytes) in one I2C transfer. After the last byte of the command is received and before the ACk bit is sent back to the master, the flash is programmed. After programming I2C bus is released, ready to receive the next segment of data.

What I have noticed is during I2C transfer the micro appears to jump to a reset vector around the time of a USI interrupt.

In the diagram above, P1.4 and P1.5 are toggled at the same inside an USI ISR when start condition is detected. P1.5 by itself is toggled as the first instruction after reset inside _c_int00() before the stack pointer is loaded. P1.4 is toggled as the first instruction inside my USI ISR and it is also toggled when the bits are successfully processed and USI is ready for the next transfer. In the middle of the diagram you can see P1.5 toggle by itself when indicates that my MCU started executing from a reset vector. About 0.1ms before that you can see line P1.4 toggle twice, first time when the USI isr begins to execute at the second time when the bit counter in USI controller is loaded to receive the next 8 bits. After the 8 bits arrive, no interrupt is generated and I2C bus is not held low. But instead, the MCU starts executing from reset vector. It is important to note that "reset" occurs during I2C transfer long before all 16 bytes of data are received and "flash write" is executed. Some times it occurs when receiving I2C address byte.

However, if MCU is programmed with only my bootloader (application address space 0xF800-FBFF is all 0xFFs), when "erase flash" command is received from the host, erasing does not executed because all bytes are already at 0xFF. After that, all I2C transfers to program flash occur without "resets".

Somehow, erasing flash causes USI interrupts (those interrupts occur much later) to misfire causing MCU to start from a reset vector. However, programming flash does not affect USI interrupts and the appplication is successfully loaded. One average, about 13 I2C transfers are succeed programming 13*16 = 208 bytes before a "restart" occurs resulting in failed I2C transfer (NACK received).

The watchdog is disabled right after SP is initialized. No other interrupts are enabled and NMI interrupt is pointing to a reset trap (infinite loop). What could cause the MCU to execute from a reset vector?

Thanks

  • Hi Gennadiy

    Did you use your demo code in the application note http://www.ti.com/lit/an/slaa600d/slaa600d.pdf as the reference ? 

  • No. However, after looking at the example you mentioned, I noticed they have a function that disables interrupts in peripherals with a note saying that "The following routines disable interrupts which are cleared by POR but not by a PUC".

    My application is using Timer A interrupts and it also uses an invalid password on watchdog register to reset and enter the bootloader. Watchdog generates PUC (power-up clear) event and restarts the processor, but what PUC does not do is reset timer registers (only reset by POR, power-on reset). When my bootloader would enable the interrupts, the timer would fire, causing periodic interrupts to occur and cause "jump to nowhere".

    All I had to do was to clear TACCTL0, TACCTL1, and TACTL registers and everything started working as expected.

**Attention** This is a public forum