This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

flash erase with UART interrupt

Hi,

In the code below, I am trying to erase a flash page in conjuction with a UART interrupt. By them selves, the interrupt and flash erase work fine, but when I put them together, the flash erase has no effect.

Would anyone have any idea how the UART interrupt is affecting my flash erase. Thanks.

#include "c8051f060.h" // SFR declarations

// -------------------

void flash_erase(int startpage, int npages)
{
char xdata* data pagePointer = 0; /

EA = 0; // temporary disable interrupts

FLSCL |= 0x01; // Enable FLASH R/WR via software
PSCTL = 0x03; // MOVX erases FLASH

pagePointer = (char xdata*)(startpage * 512);

*pagePointer = 0; // initiate the erase

PSCTL = 0x00;
FLSCL |= 0x01; // Disable FLASH R/WR via software
}

// ----------------------

void UART1_ISR (void) interrupt 20
{
if (RI1)
{
EA = 0;
flash_erase(0x1F, 1);
RI1 = 0; //clears receive flag
}
}

// ---------------

int main()
{
WDTCN = 0xDE; //disable WDT
WDTCN = 0xAD;

SFRPAGE = UART1_PAGE;
SCON1 = 0x50; // Receive enabled

EA = 1; // global interrupt enable
EIE2 |= 0x40; // Enable UART1 ISR

RI1 = 1; //trigger UART1 interrupt

return 0;

} //-----end main

  • by the way, I am using the KEIL c51 compiler with an silabs c8051f060 MCU

  • nothing in particular. I think that I had it in there as an artifact of another compiler that required main to have a return type.

  • I think you should examine the execution path after main() returns. Does it return to some code that stays in a tight loop, or restarts the program, or just runs amok, or ...

  • what I see

    UART1_ISR (void) interrupt 20
    {
    if (RI1)
      {
      EA = 0; // NOT RESTORED
      flash_erase(0x1F, 1); // MAY TAKE TOO LONG
      RI1 = 0; //clears receive flag // SHOULD BE FIRST
      }
    }
    Erik

  • [HINT]: Generally, an embedded system never returns from main().

  • I tried the change to main "void main(void)". problem still exists.

    The problem is basically that when I step past the code to erase the flash, it has no effect. The flash doesn't change.

    I reduced the code to the absolute minimum, so in this context I am not concerned about what happens after the flash erase in terms of the interrupts staying disabled.

    If I do the flash erase without the interrupt, it works just fine.

  • "I tried the change to main "void main(void)"."

    Changing the return type to void is not going to prevent main() from returning. If that were the case, then flash_erase() would not return either.

    Let's say that when main() returns, whatever called it in the first place calls it again only to immediately trigger another UART interrupt and initiate another flash erase while the first one is likely still in progress.

    So this time I'll be more direct and suggest you test after adding a "for (;;);" or "while (1);" after the "RI1 = 1;" line.

  • Here is latest code with suggested changes. I have a break point in the ISR as shown in the code at

    //#### BREAK POINT HERE #####
    RI1 = 0;

    At that break point, the code space for address 0x1f * 0x200 = 0x3E00 remains unchanged, (i.e. page not set to all 0xFF.)

    I think that what happens after that with main and returns is probably not relevant.

    #include "c8051f060.h"

    void flash_erase(int startpage, int npages)
    {
    char xdata* data pagePointer = 0;

    FLSCL |= 0x01; // Enable FLASH R/WR
    PSCTL = 0x03; // MOVX erases FLASH

    pagePointer = (char xdata*)(startpage * 512);

    *pagePointer = 0; // initiate erase

    PSCTL = 0x00;
    FLSCL |= 0x01; // Disable FLASH R/WR
    }


    void UART1_ISR (void) interrupt 20
    {
    if (RI1)
    {
    EA = 0;
    RI1 = 0;
    flash_erase(0x1F, 1);
    //#### BREAK POINT HERE #####
    RI1 = 0;
    }
    }


    void main(void)
    {
    WDTCN = 0xDE; //disable WDT
    WDTCN = 0xAD;

    SFRPAGE = UART1_PAGE;
    SCON1 = 0x50; // Receive enabled

    EA = 1; // global interrupt enable
    EIE2 |= 0x40; // Enable UART1 ISR

    RI1 = 1; //trigger UART1 interrupt
    }

  • Here is with while loops to prevent returns and again flash refuses to change


    #include "c8051f060.h"

    void flash_erase(int startpage, int npages)
    {
    char xdata* data pagePointer = 0;

    FLSCL |= 0x01; // Enable FLASH R/WR
    PSCTL = 0x03; // MOVX erases FLASH

    pagePointer = (char xdata*)(startpage * 512);

    *pagePointer = 0; // initiate erase

    PSCTL = 0x00;
    FLSCL |= 0x01; // Disable FLASH R/WR
    }


    void UART1_ISR (void) interrupt 20
    {
    if (RI1)
    {
    EA = 0;
    RI1 = 0;
    flash_erase(0x1F, 1);
    //#### BREAK POINT HERE #####
    RI1 = 0;
    while(1);
    }
    }


    void main(void)
    {
    WDTCN = 0xDE; //disable WDT
    WDTCN = 0xAD;

    SFRPAGE = UART1_PAGE;
    SCON1 = 0x50; // Receive enabled

    EA = 1; // global interrupt enable
    EIE2 |= 0x40; // Enable UART1 ISR

    RI1 = 1; //trigger UART1 interrupt
    while(1);
    }

  • FLSCL |= 0x01; // Enable FLASH R/WR
    PSCTL = 0x03; // MOVX erases FLASH

    pagePointer = (char xdata*)(startpage * 512);


    is "pagePointer" in flash?

    Erik

  • my mistake

    Forget to change SFRPAGE

    Thanks for all the input.