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.

Save Conversion data into flash

Other Parts Discussed in Thread: MSP430AFE253

Hi,

I'm trying to save the conversion data of the SD24 ADC od MSP430AFE253 into the flash memory, but it sucks. My idea was: I collect 32 conversion values, save them into an array, and then quit the ADC ISR, go back to the main program where the content of the array gets saved to the flash memory. this actions are built in an infinte loop, so that the conversion/savin of the data is continous.

Unfortunately, when I look into the memory, I notice that only oone value (0) got saved at the address 0x1040. All other memory cells seem to be untaoched. Any body has a clue?

Here is my code:

 

//*****************************************************************************
#include <msp430afe253.h>

#define   Num_of_Results   32


unsigned int results[Num_of_Results];
unsigned char lowbyte;
unsigned char highbyte;

void Write_Data(int n, char value);

void main(void)
{
  volatile unsigned int j;                  // Use volatile to prevent removal by compiler optimization
                                 

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
 
  FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator          

  SD24CTL = SD24REFON + SD24SSEL0;          // 1.2V ref, SMCLK
  SD24INCTL2 |= SD24INTDLY0;                // Interrupt on 3rd sample
  SD24CCTL2 |= SD24IE ;                     // Enable interrupt
  SD24CCTL2 |= SD24UNI ;                  // Unipolar conversion
 
  for (j = 0; j < 0x3600; j++);             // Delay for 1.2V ref startup
 
  while(1) {
      SD24CCTL2 |= SD24SC;                      // Set bit to start conversion

       for (j = 0; j < Num_of_Results; j++)
       {
        lowbyte = results[j] & 0xff;
        highbyte = results[j] >>8;
        Write_Data(2*j, lowbyte);
        Write_Data(2*j+1, highbyte);
       }
      
       __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupts

  }

}

#pragma vector=SD24_VECTOR
__interrupt void SD24AISR(void)
{
      static unsigned int index = 0;
   
      switch (SD24IV)
      {
      case 2:                                   // SD24MEM Overflow
        break;
      case 4:                                   // SD24MEM0 IFG
        break;
      case 6:                                   // SD24MEM1 IFG
        break;
      case 8:                                   // SD24MEM2 IFG
        results[index] = SD24MEM2;           // Save CH0 results (clears IFG)
        if (++index == Num_of_Results)
        {
          index = 0;    
          return;
        }
        break;
      }
}


// ----------------------------- Write_Data_To_Memory -----------------------------------------
      void Write_Data(int n, char value)
      {
        char *Flash_ptr;                          // Flash pointer
        Flash_ptr = (char *)0x1040;               // Initialize Flash pointer
       
       
       
        FCTL3 = FWKEY;                            // Clear Lock bit
        FCTL1 = FWKEY + ERASE;                    // Set Erase bit

             
        Flash_ptr = Flash_ptr-n;
        *Flash_ptr = 0;                           // Dummy write to erase Flash seg
       
        FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
       
     
        *Flash_ptr = value;                       // Write value to memory

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

      }

  • Hi,

     

    You are trying to write one value (made by two bytes) at a time. Notice that, each time you enter in the flash writing function you order to erase the flash segment. This operation erases all the information within the segment. You should erase the segment only once.

    Other thing that seems to be incorrect is that the program must wait ADC end of conversion interrupt. So, enter in LPM0 after the line    

     

    SD24CCTL2 |= SD24SC;                      // Set bit to start conversion

    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupts


    And change the ADC ISR to leave with the MCU running.

     

    Best regards,

    AES

  • aes said:

    Other thing that seems to be incorrect is that the program must wait ADC end of conversion interrupt. So, enter in LPM0 after the line    
     
    SD24CCTL2 |= SD24SC;                      // Set bit to start conversion
    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupts

    And change the ADC ISR to leave with the MCU running.

    I think the linker doen't exit the ISR. how can I ensure that the ISR runs only once (so fills the array results with 32 conversion results) and then gets back to the main prog, and saves the content of results to the flash?

    Or is there a better way to do it?

    Thanks

  • Hello,

     

    i am not using youre MSP430, so i will try to help a little bit in general.

     

    I cannot see any timeline in youre code. From my point of view i would say you really need some time bases, which tells the controller at what timing ( e.g. when the conversion result of one ADC is finished) he has to do the memory access of writing data to flash.

     

    In youre code all i see is some time independant for-loop which has no time-relation with youre ADC-Interrupt.

     

    And in general the other poster had a point when saying you only must erase youre flash segment once, then you only have to write to it, at different locations of course to store youre data correctly.

     

    Hope it helps a little bit.

    Greetings, Seb

  • MSP430-Beginner said:
    I think the linker doen't exit the ISR

    The linker never enters the ISR. The linker has nothing to do with the ISR. The linker just takes code snippets, puts them into a 'final' position and 'links' them with other code snippets that are referencing them. The linker is done long before the final binary gets written to the MSP and executed.

    MSP430-Beginner said:
    how can I ensure that the ISR runs only once

    The ISR is called when an interrupt event occurs. The end of a conversion is such an event (IFG bit is set). Reading the conversion result clears the IFG bit. And therefore the ISR is not entered again if you exit it. However, if the IFG bit gets set again (because a new conversion is done), it is called again.

    The problem with your code is, that teh main code doesn't wait until the wanted number of results is available. It starts the conversion and then immediately tries to calculate with esults that do not exist yet.

    There are two ways to synchronize the process. First one, you define a vloatile global variable that is set to 0 by main. When the ISR has collected 32 results (index is reset) it also sets this variable to 1. Main waits in a loop for the variable becoming 1, clears it again and begins teh calculation.

    A different approac is to enter LPM when the conversion has been started. When the 32 results are collected, the ISR calls the LPM_EXIT intrinsic so main continues working as soon as the ISR exits. Sinc eon the previous 31 calls to the ISR this intrinsic is not called, main remains dormant.

  • Hi, 

    Just check whether this code gives  you the solution or not??

    --

    --

     

    void FLASH_WRITE(unsigned char value)

    {

    char *Flash_ptr;                          

      unsigned int i;

     

      Flash_ptr = (char *) 0x1040;              

      FCTL1 = FWKEY + ERASE;                    

      FCTL3 = FWKEY;                            

      *Flash_ptr = 0;                           

     

      FCTL1 = FWKEY + WRT;                      

     

      for (i=0; i<64; i++)

      {

        *Flash_ptr++ = value;                   

      }

     

      FCTL1 = FWKEY;                            

      FCTL3 = FWKEY + LOCK;

    }

     

    --

    Regards,

    Mrigank

  • Hi,

    If this will still not give u the solution then, change the pointer to 1000 instead of 1040 and then check whether this is working or not?  

  • Jens-Michael Gross said:
    you define a volatile global variable that is set to 0 by main. When the ISR has collected 32 results (index is reset) it also sets this variable to 1. Main waits in a loop for the variable becoming 1, clears it again and begins teh calculation.

    Thanks for the details.

    I changed my program and it works fine now. For those who my be interested, plz find my code below.

    Now i have another question. In the beginning I started writing the data into segment A of the information memory, but it did not work. I think the reason, is that, when I compile my program, and before running it, the cells with the addresses: 0x10fd, 0x10fc, 0x10fb, 0x10fa contain respectively: 7c 8e 6a 8d. What do these refer to?

    How can I check if the memory has already been used or not?

     

    Is the way I'm writing the data, is it "the bolck write" mentioned in the data sheet which allows saving time or not?

     

    Thanks!

     

    #include <msp430afe253.h>

    #define   Num_of_Results   33


    unsigned int results[Num_of_Results];
    unsigned char lowbyte;
    unsigned char highbyte;
    volatile unsigned int synchr;

    void Write_Data(int n, char value);

    void main(void)
    {
      volatile unsigned int j;                  // Use volatile to prevent removal
                                                // by compiler optimization

      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
     
      FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator          

      SD24CTL = SD24REFON + SD24SSEL0;          // 1.2V ref, SMCLK
      SD24INCTL2 |= SD24INTDLY0;                // Interrupt on 3rd sample
      SD24CCTL2 |= SD24IE ;                     // Enable interrupt
      SD24CCTL2 |= SD24UNI ;                    // Unipolar conversion
     
      for (j = 0; j < 0x3600; j++);             // Delay for 1.2V ref startup
     
       
          synchr = 1;
          SD24CCTL2 |= SD24SC;                      // Set bit to start conversion
          __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupts
          
          while (synchr);

       
           for (j = 0; j < Num_of_Results; j++)
         {
            lowbyte = results[j] & 0xff;
            highbyte = results[j] >>8;
            Write_Data(2*j, lowbyte);
            Write_Data(2*j+1, highbyte);
         }
         

    }

    #pragma vector=SD24_VECTOR
    __interrupt void SD24AISR(void)
    {
          static unsigned int index = 0;
       
          switch (SD24IV)
          {
          case 2:                                   // SD24MEM Overflow
            break;
          case 4:                                   // SD24MEM0 IFG
            break;
          case 6:                                   // SD24MEM1 IFG
            break;
          case 8:                                   // SD24MEM2 IFG
            results[index] = SD24MEM2;              // Save CH2 results (clears IFG)
            if (++index == Num_of_Results)
            {
                index = 0;
                synchr = 0;
                SD24CCTL2 &= !SD24SC;                      // Set bit to STOP conversion
                 __bic_SR_register_on_exit(LPM0_bits);        // Exit LPM0
                return;
            }
            return;
          }
    }


    // ----------------------------- Write_Data_To_Memory -----------------------------------------
          void Write_Data(int n, char value)
          {
            char *Flash_ptr;                          // Flash pointer
            Flash_ptr = (char *)0xfe00;               // Initialize Flash pointer
           
           
            FCTL3 = FWKEY;                            // Clear Lock bit
           
            if (n == 0)
            {

               FCTL1 = FWKEY + ERASE;                    // Set Erase bit
               *Flash_ptr = 0;                           // Dummy write to erase Flash seg
            }
                 
            Flash_ptr = Flash_ptr-n;
           
            FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
           
         
            *Flash_ptr = value;                       // Write value to memory

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

          }

     

     

**Attention** This is a public forum