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.

MSP430 - Flash Write and Read

Other Parts Discussed in Thread: MSP430G2553

hi,

i am using the following code for my project. In this test code i have given 10 characters in an array "Wdata"

i am trying to write this data in Flash.

after writing has done. i am reading the data from same memory. whats the problem is after reading the data in "Rdata[10]" is

 { '7', '.' , '2' , '.' , '0' , '.' , '4' , '.' , '2' , '.' };

can anyone tell me how to use the flash write  correctly..!

here the code is..

#include <msp430.h>

char  Rdata[10];                              
char Wdata[10]={'7','2','0','4','2','8','6','2','2','8'};


// Function prototypes


void read (void);
void write (void);

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  if (CALBC1_1MHZ==0xFF)                    // If calibration constant erased
  {                                            
    while(1);                               // do not load, trap CPU!!    
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_8MHZ;                    // Set DCO to 8MHz
  DCOCTL = CALDCO_8MHZ;
  FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator

write();

read();   

while(1);  //debugging


}

void read()

{

char *Flash_ptr;

 unsigned int i;

  Flash_ptr = (char *) 0x1040; 

 FCTL1 = FWKEY + ERASE;                    // Set Erase bit
  FCTL3 = FWKEY;                            // Clear Lock bit
  *Flash_ptr = 0;                          // Dummy write to erase Flash segment D
  FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation

  for (i=0; i<10; i++)
  {
    Rdata[i++] = *Flash_ptr++;         
  }

  FCTL1 = FWKEY;                            // Clear WRT bit
  FCTL3 = FWKEY + LOCK;                     // Set LOCK bit

}

void write ()
{
  char *Flash_ptr;                          // Flash pointer
  unsigned int i;

  Flash_ptr = (char *) 0x1040;              // Initialize Flash pointer
  FCTL1 = FWKEY + ERASE;                    // Set Erase bit
  FCTL3 = FWKEY;                            // Clear Lock bit
  *Flash_ptr = 0;                           // Dummy write to erase Flash segment

  FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation

  for (i=0; i<10; i++)
  {
    *Flash_ptr++ = Wdata[i++];                   // Write value to flash
  }

  FCTL1 = FWKEY;                            // Clear WRT bit
  FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
}

thank you!

  • Hi,

    you write only every 2nd character to flash with that loop. You also read only the first 5 characters. Dont increment i twice/iteration.

    You should also poll the fctl3 register before you start any flash operation:

    while ((FCTL3 & BUSY) != 0);

  • Unfortunately, you have not mentioned for which MSP430 family device you wrote that code.

    I assume you have neither a MSP430x5xx nor a MSP430x6xx family device, because you use register FCTL2 . IIRC for the other devices the flash timing must be in the range from approximately 257 kHz to approximately 476 kHz. MCLK/3 = 8/3 MHz violates the flash timing. Please check the device-specific data sheet.

    Hope it helps,
    Christian

  • sorry ! i forgot to mention the controller , i am using msp430g2553

  • I changed my code as per your suggestion but didt works...still i am facing the same problem

    void write(void)
    {
      char *Flash_ptr;                          // Flash pointer
      unsigned int i;

      Flash_ptr = (char *) 0x1000;              // Initialize Flash pointer
      FCTL1 = FWKEY + ERASE;                    // Set Erase bit
      FCTL3 = FWKEY;                            // Clear Lock bit
      *Flash_ptr = 0;                           // Dummy write to erase Flash segment

      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation

      for (i=0; i<10; i++)
      {
          while ((FCTL3 & BUSY) != 0);
       *Flash_ptr++ = CFGnumber[i];                   // Write value to flash
      }

      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
    }


    void read (void)
    {

          char  *Flash_ptr;                          // Flash pointer
          unsigned int i;

          Flash_ptr = (char *) 0x1000;              // Initialize Flash pointer


          for(i=0;i<10;i++)
          {
              while ((FCTL3 & BUSY) != 0);
              FSTnumber[i++]=*Flash_ptr++;
          }

    }

  • You have to remove the second increment statement of i in your read() function, too:

    void read (void)
    {

          char  *Flash_ptr;                          // Flash pointer
          unsigned int i;

          Flash_ptr = (char *) 0x1000;              // Initialize Flash pointer


          for(i=0;i<10;i++)
          {
              while ((FCTL3 & BUSY) != 0);
              FSTnumber[i]=*Flash_ptr++;
          }

    }

     

     

  • yeah.. its mistake..

    thank you!

  • I'm glad to here that you were successful!

    mark sonnentag said:

    You should also poll the fctl3 register before you start any flash operation:

    while ((FCTL3 & BUSY) != 0);

    As long as you don't initiate erase/write operations from RAM you don't need to pool the busy flag. When initiating from within flash memory, all timing is controlled by the flash controller and the CPU is held while erase/write operation. After erase/write completes, the CPU resumes code execution with the instruction following the erase/write operation.

  • The MSP430 that I use allows to start an erase operation of a flash bank while the code that is in another bank is executed at the same time. Then its also possible to start a flash operation from RAM and another one from Flash while the other one is still running, then you have a problem if you didnt add this line to the code that is executed from flash memory. Those are errors that nobody wants to debug if they can be that easily avoided.

    Therefore it is best practice to poll this flag before every operation, at least in my opinion.

  • mark sonnentag said:
    The MSP430 that I use allows to start an erase operation of a flash bank while the code that is in another bank is executed at the same time.

    Check the errata sheet. On some MSPs, the code of a different bank isn't executed but the CPU crashes instead. (and erasing the bank you're executing from doesn't make much sense). The 5438 is one of them. In my code, I load a few variables on stack with values that resolve to the initial write, the waiting loop for the busy bit and a return, then I call the variables on the stack as a function.

    mark sonnentag said:
    Then its also possible to start a flash operation from RAM and another one from Flash while the other one is still running,

    indeed, if ruhnning flash code while erasign a different bank works, and you do not erase the bank with the interrupt vectors, (which includes info memory) and an interrupt happens and this interrupt initiates a flash write, this would indeed lead to conflicting flash writes. For this case you can set a semaphore at the begin of your flash write function (assuming you only have one of them). Also, it wouldn't make ans sense continuing from flash erase to flash write while the erase is still in progress. However, the wait whiel busy during flash erase should be move to ram due to the beforementiond erratum. It doesn't hurt if your MSP doesn't exhibit this problem, as the code will still run, but is also portable to MSPs which do have the problem.
    (many 'but it worked on the other MSP' errors could be avoided this way)

**Attention** This is a public forum