Background:
I am trying to write an 8-bit value to Info C block of FLASH on the MSP430F5529. Info C starts at address 0x1880, so I use a #define
to keep this value:
#define INFOC_REGISTER 0x1880
In my main function I make a call to a method which is intended to write this 8-bit value (let's just say 0x01 for the sake of argument) to the lowest byte of address 0x1880:
writeValueToFlash(data);
This function has two calls to functions declared in flashctl.c, which I got from MSP430Ware_3_80_05_04. My writeValueToFlash()
function is as follows:
/*********************************************************************
* @fn bool writeValueToFlash(uint8_t data)
* @brief Write 8-bit value to FLASH
* @param data - 8-bit value
* @return bool - Returns true
*/
bool writeValueToFlash(uint8_t data) {
FlashCtl_eraseSegment((uint8_t*)INFOC_REGISTER);
FlashCtl_write8((uint8_t*)data, (uint8_t*)INFOC_REGISTER, 1);
return true; // Baud rate changed
}
Below are the two functions from the MSP430Ware package. I have not made any changes to these functions, except for adding the header commentary from the flashctl.h file:
//*******************************************************************
//
//! \brief Erase a single segment of the flash memory.
//!
//! For devices like MSP430i204x, if the specified segment is the information
//! flash segment, the FLASH_unlockInfo API must be called prior to calling
//! this API.
//!
//! \param flash_ptr is the pointer into the flash segment to be erased
//!
//! \return None
//
//********************************************************************
void FlashCtl_eraseSegment(uint8_t *flash_ptr){
//Clear Lock bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY;
//Set Erase bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY + ERASE;
//Dummy write to erase Flash seg
*flash_ptr = 0;
//test busy
while(HWREG8(FLASH_BASE + OFS_FCTL3) & BUSY)
{
;
}
//Clear ERASE bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY;
//Set LOCK bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY + LOCK;
}
//********************************************************************
//
//! \brief Write data into the flash memory in byte format, pass by reference
//!
//! This function writes a byte array of size count into flash memory. Assumes
//! the flash memory is already erased and unlocked. FlashCtl_eraseSegment can
//! be used to erase a segment.
//!
//! \param data_ptr is the pointer to the data to be written
//! \param flash_ptr is the pointer into which to write the data
//! \param count number of times to write the value
//!
//! \return None
//
//********************************************************************
void FlashCtl_write8(uint8_t *data_ptr,
uint8_t *flash_ptr,
uint16_t count)
{
//Clear Lock bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY;
//Enable byte/word write mode
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY + WRT;
while(count > 0)
{
//test busy
while(HWREG8(FLASH_BASE + OFS_FCTL3) & BUSY)
{
;
}
//Write to Flash
*flash_ptr++ = *data_ptr++;
count--;
}
//Clear WRT bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY;
//Set LOCK bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY + LOCK;
}
The Problem:
The issue I am facing is that when I try to write "data" (or 0x01
in this case) to the INFOC_REGISTER
(address 0x1880
), it does not work properly. When I attempt to erase the block, I end up with something along the lines of FF7E
in that memory location (this fluctuates somewhat - it is not always FF7E
, it changes every time I restart the micro and try the erase again), and when I attempt to write 0x01
I end up with something similar like FF50
in that memory location. This value also fluctuates. I am expecting FF01
.
Are there any obvious mistakes in the way I am erasing or writing to FLASH? I know I had it working at one point quite some time ago but I am not sure what I would have changed that could cause this issue.
Update:
Per CL's answer, I have modified the code as follows, but still seem to have similar issues.
#define INFOC_REGISTER ((uint8_t*)0x1880)
bool writeValueToFlash(uint8_t data) {
FlashCtl_eraseSegment(INFOC_REGISTER);
FlashCtl_write8(&data, INFOC_REGISTER, 1);
}
It appeared to work the first time (I wrote 0x08
and it worked correctly), but then when I went back and tried to change it to 0x01
or 0x0A
it did not. After stepping over the FlashCtl_eraseSegment()
function call it changed to FF0C, and when I stepped over the FlashCtl_write8()
function (with data = 0x0A
) it just went back to FF08.
Further Update:
Sometimes it seems to work, other times not. It is very flaky....
flash_ptr
inFlashCtl_eraseSegment
should bevolatile
. \$\endgroup\$(uint8_t*)data
in the first function is already a nonsense. \$\endgroup\$uint8_t data = 1
, then cast(uint8_t *)data
is casting data's value to an address and, for instance,*(uint8_t *)data
will now access the memory (read or write) with the address0x0001
which is obviously not what you wanted. \$\endgroup\$