Background:
Estoy intentando escribir un valor de 8 bits en el bloque de información C de FLASH en el MSP430F5529. La información C comienza en la dirección 0x1880, así que uso un #define
para mantener este valor:
#define INFOC_REGISTER 0x1880
En mi función principal hago una llamada a un método que está destinado a escribir este valor de 8 bits (digamos 0x01 por el bien del argumento) en el byte más bajo de la dirección 0x1880:
writeValueToFlash(data);
Esta función tiene dos llamadas a funciones declaradas en flashctl.c, que obtuve de MSP430Ware_3_80_05_04. Mi función writeValueToFlash()
es la siguiente:
/*********************************************************************
* @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
}
A continuación se muestran las dos funciones del paquete MSP430Ware. No he realizado ningún cambio en estas funciones, excepto para agregar el comentario del encabezado del archivo flashctl.h:
//*******************************************************************
//
//! \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;
}
El problema:
El problema al que me estoy enfrentando es que cuando intento escribir "datos" (o 0x01
en este caso) en el INFOC_REGISTER
(dirección 0x1880
), no funciona correctamente. Cuando intento borrar el bloque, termino con algo parecido a FF7E
en esa ubicación de memoria (esto fluctúa un poco, no siempre es FF7E
, cambia cada vez que reinicio el micro y vuelvo a intentar borrar) ), y cuando intento escribir 0x01
termino con algo similar como FF50
en esa ubicación de memoria. Este valor también fluctúa. Estoy esperando FF01
.
¿Hay errores obvios en la forma en que estoy borrando o escribiendo en FLASH? Sé que lo tuve funcionando en algún momento hace bastante tiempo, pero no estoy seguro de qué cambio habría podido causar este problema.
Actualizar:
Según la respuesta de CL, modifiqué el código de la siguiente manera, pero parece que todavía tengo problemas similares.
#define INFOC_REGISTER ((uint8_t*)0x1880)
bool writeValueToFlash(uint8_t data) {
FlashCtl_eraseSegment(INFOC_REGISTER);
FlashCtl_write8(&data, INFOC_REGISTER, 1);
}
Parecía que funcionaba la primera vez (escribí 0x08
y funcionó correctamente), pero cuando regresé y traté de cambiarlo a 0x01
o 0x0A
no lo hizo. Después de pasar por encima de la función FlashCtl_eraseSegment()
, la llamada cambió a FF0C, y cuando paso por encima de la función FlashCtl_write8()
(con data = 0x0A
), simplemente regresó a FF08.
Actualización adicional:
A veces parece funcionar, otras veces no. Es muy escamoso ....