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.

Large data model gives problems when reading and writing memory below 0x10000

Hi all!

I have a question about flash, i have made a set of functions to read and write to flash on the MPS430F5436A. I had to switch to the large data model so that i can reach the registers above 0x10000, this works fine, i can read and write to those registers with no problem (using unsigned long pointers).

I all so made some functions to write to the lowere memory addresses (like the info and bsl memory banks). These functions worked fine before i switched to the large data model (by setting the large data model option on in Code Composer).

Does anybody have a idea? All sugestions are welcome!

The value that i read back is 0xFF which means that noting is written?

But now they don't work for the lower addresses, below a simpel one byte write and read functions:


char ReadOneByte(char * StartAddress){
TempByte = 0;
*ReadMemoryPointerInfoOrBSL = 0;
ReadMemoryPointerInfoOrBSL = StartAddress;

TempByte = *ReadMemoryPointerInfoOrBSL;

return TempByte;
}


void WriteOneByte(char * StartAddress, char value){


FCTL3 = FWKEY; // Clear Lock bit
FCTL1 = FWKEY + ERASE; // Set Erase bit
*ReadMemoryPointerInfoOrBSL = 0;
*WriteMemoryPointer2 = 0;

WriteMemoryPointer2 = StartAddress;

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

*WriteMemoryPointer2 = value; // Write value to flash


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

*Update

When i use long as data type i then i can read an write to to lower registers, so when i use long pointers and variables then i can write and read data. But i don't think this is the solution because i write byte for byte, when i increment the pointer is see that it skips 4 bytes, but this way i lose space?

Anybody have a suggestion?

  • You don’t need different read functions for above and below 64k. What works for above will also work for below. Just for the info/BSL write, you’ll need a switch in the code that takes care for BSL area unprotection and the different segment size of info memory. But this you needed before too, to separate main memory from info memory writes.

    With large code model, the size of a pointer is 20(32) bit. But this has nothing to do with the size of an element it points to (this always was 8/16/32 bit for char/int/long) and even more for other types like struct or double.

    But the code you posted  looks suspicious.

    How are ReadMemoryPointerInfoOrBSL and Write… defined and initialized? At start of your function, you write 0 to the address they are pointing to, probably causing havoc. Especially the double assignment in the write function, when erase is already enabled and you didn’t assign the destination address yet to the write pointer, is most likely not what you want.

    As a hint, currently you erase a whole segment to write one single byte. You should check the memory location first. If it is still 0xff, then there is no need to erase anything.
    It makes not much sense to have a write funciton that can only write one byte per 128/512 byte flash segment (and always erases the other bytes in the segment).
    Also, you write only one byte, but use double word write mode. Set WRT instead of BLKWRT for byte write mode.
    Best, you should pass a pointer to a char array to the function, along with a size info. So the function can determine whether a segment needs to be erased, or saved/erased, then reprogrammed with untouched previous content that is not written. It also can write multiple bytes (as DWORDS as long as there are 4 bytes to write, padded with 0xFF if not) with one call.

  • Hi Jens-Michael, 

    First of all thank you for replying to my post! The two functions i showed are indeed just for single read and write but can be considerd as debug functions. The read function is used in the a seperate segment read fuction. In this funciton i check for the segment size. 

    I changed the code with your feedback (i still do the segment erase here), and the first read and write operations go good. After the first read and write operation the second read and write functions go wrong. i write and read all the time to the same address (info D starting addres). Below is the current code, could you take a look at it?

    Many thanks in advance!

    char ReadOneByte(char* StartAddress){
    TempByte = 0;

    ReadMemoryPointerInfoOrBSLD = StartAddress;

    TempByte = *ReadMemoryPointerInfoOrBSLD;

    return TempByte;
    }


    void WriteOneByteBSL(char * StartAddress, char value){


    FCTL3 = FWKEY; // Clear Lock bit

    WriteMemoryPointerInfoOrBSLD = StartAddress;

    FCTL1 = FWKEY + ERASE; // Set Erase bit


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

    *WriteMemoryPointerInfoOrBSLD = value; // Write value to flash


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

  • Currently, you do not erase at all. After setting the ERASE bit, you have to perform a write to any address of the segment you want to erase. So four your simple example code, you’ll have to write to *WriteMemoryPointerInfoOrBSLD twice – but after you set the pointer to the correct destination address.

  • Hi Jens,

    Many thanks for your feedback it works! For furher reference i have posted the working code (this is still without your erase check, i'm gonna fix that to):

    void WriteByte(char * StartAddress, char value){


        FCTL3 = FWKEY; // Clear Lock bit

        WriteMemoryPointerInfoOrBSLD = StartAddress;

        FCTL1 = FWKEY + ERASE; // Set Erase bit

        *WriteMemoryPointerInfoOrBSLD = 0;


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

        *WriteMemoryPointerInfoOrBSLD = value; // Write value to flash


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

    I have only one more question regarding flash read and write, i'm using the large data model so that i can write and read the adresses of the flash memory above 0x10000. Now i can use long pointers to store the lagerer then 16 bit addresses. But when i want to write a segment and write byte for byte the long pointer icrments ofcourse with four bytes. 

    My question is: is there a way to use the small data model and still reach addresses above 0x10000? Or what is the best way to wrtie byte for byte using a long pointer (to hold the adress)?

    Many thanks in advance!

  • The size of a pointer refers to the size of the address value it holds. It is 16 bit for small code model and 32 bit (20 of them used) for large code model.
    However, the increment is determined by the type it points to. So a char* increments by 1, no matter whether it is a 16 or 32 bit address that is incremented.
    And a long* has always been incremented by 4, even in small code model.

    So in large code model, you can still use a char* and it points to a char and increments by one, even though the address it points top can be 20 bit, while in small code model, the address would be 16 bit only.

    You can do with small code model (which is up to 10% smaller and faster, since all references to data are only one and not two words)
    The compilers provide intrinsics to read and write to a 32 bit address. Something like "write_long(long address, long data)" and "write_int(long address, int data).
    The compiler takes the long address for the adddress and the data and generates the proper assembly code.
    Note that here, the address is a normal long value, not a pointer.

  • Hi Jens!

    Once again, thank you for your reply! Your answer make sense i will verify this today or monday! Thank you for your input! I will get back to you.

**Attention** This is a public forum