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.

MSP430G2744 Problem Reading from Main Flash

Other Parts Discussed in Thread: MSP430G2744

Hello there guys! I'm struggling with this problem and hope you can help me to figure out my mistake.

I've searched on the forum but couldn't find anyone with the same problem as mine.

I successfully implemented functions to read and write on the information memory, the datasheet had all information I needed. But I have this strange problem to read from the main flash area. Right now I cannot read more then 156 bytes from the main flash, if I try to, my system dont work at all.

Here is my function to read from flash:

#define FLASH_PTR_SEG_D         (0x1000)        //Pointer to segment D of information memory
#define FLASH_PTR_SEG_C         (0x1040)        //Pointer to segment C of information memory
#define FLASH_PTR_SEG_B         (0x1080)        //Pointer to segment B of information memory
#define FLASH_PTR_SEG_A         (0x10C0)        //Pointer to segment A of information memory

#define FLASH_PTR_SEG_4         (0xF600)        //Pointer to segment 4 of main memory
#define FLASH_PTR_SEG_3         (0xF800)        //Pointer to segment 3 of main memory
#define FLASH_PTR_SEG_2         (0xFA00)        //Pointer to segment 2 of main memory

#define FLASH_INFO_SEG_SIZE    (0x40)    // 64 bytes per segment of information memory
#define FLASH_MAIN_SEG_SIZE   (0x200)    //512 bytes per segment of main memory
   
 typedef enum
 {
   FLASH_SEG_D,   //Information memory
   FLASH_SEG_C,   //Information memory
   FLASH_SEG_B,   //Information memory
   FLASH_SEG_A,   //Information memory
   FLASH_SEG_4,   //Main memory
   FLASH_SEG_3,   //Main memory
   FLASH_SEG_2,   //Main memory   
   FLASH_NUM_SEG
 }flash_seg_t;

#define FLASH_FIRST_INFO_SEG FLASH_SEG_D
#define FLASH_FIRST_MAIN_SEG FLASH_SEG_4

static uint16_t flash_address[FLASH_NUM_SEG] = {FLASH_PTR_SEG_D,     //Lookup table for segment address
                                                FLASH_PTR_SEG_C,
                                                FLASH_PTR_SEG_B,
                                                FLASH_PTR_SEG_A,
                                                FLASH_PTR_SEG_4,
                                                FLASH_PTR_SEG_3,
                                                FLASH_PTR_SEG_2};

/*!
* @brief Reads data from flash memory
* @param none
* @return none
*/
error_code_t flash_read_seg(flash_seg_t segment, uint16_t begin, uint16_t size, uint8_t *destiny)
{
  uint16_t      max_size;
  error_code_t  error;
  
  error = ERROR_NONE;
  
  if(segment < FLASH_FIRST_MAIN_SEG) //If segment is at information memory
  {
    max_size = FLASH_INFO_SEG_SIZE;
  }
  else
  {
    max_size = 156; //This should be FLASH_MAIN_SEG_SIZE but if I make this number 1 byte bigger than 156, the system crashes!
  }
  
  //We can only read if segment is in the correct range
  if( (segment < FLASH_NUM_SEG) && (destiny != NULL) && ( (begin + size) < max_size))
  {

    uint16_t    *p_seg;
    uint16_t     index;
    uint16_t     final_index;
    
    final_index = begin+size;
    
    p_seg = (uint16_t *)flash_address[segment];     //Points to start of segment
    
    for( index = begin; index < final_index; index++) 
    {
      destiny[index] = (uint8_t)p_seg[index];
    }

  }
  else
  {
    error = ERROR_INVALID_PARAMETER;
  }
  
  return error;
}

--------------------------

I believe I have put all information necessary! But let me know if you guys want to see more!

I hope this have not been asked before, I did use the search! :)

Thanks in advance! BR.

  • destiny[index]

    Is destiny array in ram,? you are running out of ram.

    If you are copying flash segments to other flash segments, you have to enable flash writing,

    And why not copy words instead of bytes?, don't forget to index +=2 if you do that.

    Best is to never move any data (just bad programming) but have flexible start and end pointers as stored variables.

  • Thanks for your answer Tony!

    Yes, destiny is in ram. It is defined by the module that calls the function to read from the flash memory.

    I need to move data from flash to ram because those data 1- change a lot and 2- i need to do some fast calculations with them. But at the same time they cannot be lost with a power down, so I need to save them in flash too.

    My compiler gives me this information about memory usage:

    5 948 bytes of CODE memory
    603 bytes of DATA memory (+ 54 absolute )
    68 bytes of CONST memory

    MSP430G2744 has 1KB of RAM, so I believe I'm not running out of it.

    Also, I don't see how a change of value on the variable max_size would change RAM usage, or am I missing something here? Would you mind talking more about it? 

  • what does this do: uint8_t *destiny)

    A 8bit integer?, is that OK?


    I guess you could not use the C function that copies it at boot-up
    as you have to do different segments that don't all fit in ram, this may not work for you.

    DATA16_I   (RAM)     Data initialized by copying from DATA16_ID
    DATA16_ID  (FLASH)   Initializers for DATA<nn>_I

     

  • It is ok. It defines a pointer to an unsigned integer 8 bit data. It's C99 syntax.

    You mean I could instruct my linker to get the value of initialization of my variables on flash? I'm not familiar with DATA16_ID al all. But assuming it does what I said, I cannot do it. Because this data change a lot and my product needs to run for 20 years. I need to save my variables in different places of flash to prevent erasing the segments and increase their life time.

  • OK guys! I've found my problem. Looks like it is a C or compiler/optimization problem. If someone had a good explanation for it, please, let us know!!

    What I have changed that solve the problem was:

    Instead of this:

        for( index = begin; index < final_index; index++) 
        {
          destiny[index] = (uint8_t)p_seg[index];
        }

    I used this:

        for( index = begin; index < final_index; index++) 
        {
          *destiny = (uint8_t)*p_seg;
          destiny++;
          p_seg++;
        }

    And everything is working now. Sorry for the question! But if someone have a clue on why the first code is wrong, please, let me know! It is always good to learn something new.

  • Do you always call this routine with begin = 0? If not, it is ignored and treated as if it is 0.

    I do not think optimization has anything to do with this. It is the proper use of pointers that matters.

  • Here you can find the answer to your question: http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/66903.aspx?pi307167=1 > Memory Model!

  • p_seg is an uint16_t*. So it increments in words, even though you cast the read word to uint_8t then.

    Instead of
    destiny[index] = (uint8_t)p_seg[index];
    try
    destiny[index]=((uint8_t*)p_seg)[index];

    Or make p_seg an uint8_t*. Note that the type of p_seg determines the data size (8,16,32, whatever), not the pointer size (which is always 16 or 20 bit depending on data model). So if you transfer bytes, make it an uint8_t * type.

**Attention** This is a public forum