EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Problems with EEPROM Writes on HC9S12XD256

Started by "Tennies, Joseph C." December 4, 2009
I have been trying to write to the EEPROM on the HC9S12XD256 processor
and have been having problems getting it to write.

The OSC is 12 MHz, but we run the PLL to bring it up to 48 MHz. Our
EDIV is set to 60 (with no PRDIV8).

The following code is on FreeScale CodeWarrior 4.7. Is there something
blatently obvious that I'm doing wrong? (I know I need timeouts instead
of infinite while loops.) Currently this code does not write anything
to the EEPROM.

void write_eeprom( uint16_t addr, uint16_t data)
{
uint16_t *sectorBaseAddr;
uint16_t loWord;
uint16_t hiWord;
uint16_t tickNow;
uint8_t eepromStatus;

if ( ECLKDIV | ECLKDIV_EDIVLD_MASK )
{
while( !(ESTAT & ESTAT_CBEIF_MASK) );

if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}

//*********************************************************************
// Preserve other bytes in sector

//*********************************************************************

/* Get the base address of the sector to erase */
sectorBaseAddr = (uint16_t *)(addr & ~0x03);

if ( !( sectorBaseAddr >= (uint16_t *)0xE00 && sectorBaseAddr <
(uint16_t *)0xF00 ) )
{
pet_watchdog();
return;
}

/* Preserve the current sector contents */
loWord = sectorBaseAddr[0];
hiWord = sectorBaseAddr[1];

//*********************************************************************
// Determine which word the new data occupies

//*********************************************************************
if((addr & 0x02) == 0)
{
loWord = data;
}
else
{
hiWord = data;
}

/* Write first word */
sectorBaseAddr[0] = loWord;
ECMD = EEPROM_CMD_SECTOR_MODIFY;
ESTAT |= ESTAT_CBEIF_MASK;
while ( !(ESTAT & ESTAT_CCIF_MASK) );

/* write second word */
while( !(ESTAT & ESTAT_CBEIF_MASK) );
if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}
/* Write second word */
sectorBaseAddr[1] = hiWord;
ECMD = EEPROM_CMD_WORD_PROGRAM;
ESTAT |= ESTAT_CBEIF_MASK;
while ( !(ESTAT & ESTAT_CCIF_MASK) );

/* write second word */

while( !(ESTAT & ESTAT_CBEIF_MASK) );

if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}
}
/* Reset the watchdog */
pet_watchdog();

} // end of write_eeprom

Programmers work long hours trying to design stuff that keeps them from
having to work long hours. -David Allen "Making It All Work"

Joseph Tennies

Senior Software Engineer

Esterline Control Systems - AVISTA



I don't see an erase before the write.

-rob

You don't want to read-modify-write the ESTAT because writing a one clears
the flags so change that to

ESTAT = ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK;

And

ESTAT = ESTAT_CBEIF_MASK;

I do a SECTOR ERASE and then two WORD PROGRAM commands.

Also, I've been burned by the ECLKDIV register. Make sure you ONLY WRITE TO
ECLKDIV ONCE.

_____

From: 6... [mailto:6...] On Behalf Of
Tennies, Joseph C.
Sent: Friday, December 04, 2009 1:58 PM
To: 6...
Subject: [68HC12] Problems with EEPROM Writes on HC9S12XD256

I have been trying to write to the EEPROM on the HC9S12XD256 processor
and have been having problems getting it to write.

The OSC is 12 MHz, but we run the PLL to bring it up to 48 MHz. Our
EDIV is set to 60 (with no PRDIV8).

The following code is on FreeScale CodeWarrior 4.7. Is there something
blatently obvious that I'm doing wrong? (I know I need timeouts instead
of infinite while loops.) Currently this code does not write anything
to the EEPROM.

void write_eeprom( uint16_t addr, uint16_t data)
{
uint16_t *sectorBaseAddr;
uint16_t loWord;
uint16_t hiWord;
uint16_t tickNow;
uint8_t eepromStatus;

if ( ECLKDIV | ECLKDIV_EDIVLD_MASK )
{
while( !(ESTAT & ESTAT_CBEIF_MASK) );

if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}
//*********************************************************************
// Preserve other bytes in sector

//*********************************************************************

/* Get the base address of the sector to erase */
sectorBaseAddr = (uint16_t *)(addr & ~0x03);

if ( !( sectorBaseAddr >= (uint16_t *)0xE00 && sectorBaseAddr <
(uint16_t *)0xF00 ) )
{
pet_watchdog();
return;
}

/* Preserve the current sector contents */
loWord = sectorBaseAddr[0];
hiWord = sectorBaseAddr[1];
//*********************************************************************
// Determine which word the new data occupies

//*********************************************************************
if((addr & 0x02) == 0)
{
loWord = data;
}
else
{
hiWord = data;
}

/* Write first word */
sectorBaseAddr[0] = loWord;
ECMD = EEPROM_CMD_SECTOR_MODIFY;
ESTAT |= ESTAT_CBEIF_MASK;
while ( !(ESTAT & ESTAT_CCIF_MASK) );

/* write second word */
while( !(ESTAT & ESTAT_CBEIF_MASK) );
if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}
/* Write second word */
sectorBaseAddr[1] = hiWord;
ECMD = EEPROM_CMD_WORD_PROGRAM;
ESTAT |= ESTAT_CBEIF_MASK;
while ( !(ESTAT & ESTAT_CCIF_MASK) );

/* write second word */

while( !(ESTAT & ESTAT_CBEIF_MASK) );

if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
{
ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
}
}
/* Reset the watchdog */
pet_watchdog();

} // end of write_eeprom

Programmers work long hours trying to design stuff that keeps them from
having to work long hours. -David Allen "Making It All Work"

Joseph Tennies

Senior Software Engineer

Esterline Control Systems - AVISTA





Also, If you are using the CodeWarrior BDM to debug, by default the BDM
does not read the contents of the the Flash / EEPROM when stopped /
single stepping. This means you will only see the original values of the
EEPROM, not your updated ones.

You can change this by editing the debugging memory map, and changing
the entry for EEPROM to allow refresh memory when halting.

David

Dan White wrote:
>
>
>
>
> You don't want to read-modify-write the ESTAT because writing a one clears
> the flags so change that to
>
> ESTAT = ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK;
>
> And
>
> ESTAT = ESTAT_CBEIF_MASK;
>
>
>
> I do a SECTOR ERASE and then two WORD PROGRAM commands.
>
>
>
> Also, I've been burned by the ECLKDIV register. Make sure you ONLY WRITE TO
> ECLKDIV ONCE.
>
>
>
>
>
> _____
>
> From: 6... [mailto:6...] On Behalf Of
> Tennies, Joseph C.
> Sent: Friday, December 04, 2009 1:58 PM
> To: 6...
> Subject: [68HC12] Problems with EEPROM Writes on HC9S12XD256
>
>
>
>
>
> I have been trying to write to the EEPROM on the HC9S12XD256 processor
> and have been having problems getting it to write.
>
> The OSC is 12 MHz, but we run the PLL to bring it up to 48 MHz. Our
> EDIV is set to 60 (with no PRDIV8).
>
> The following code is on FreeScale CodeWarrior 4.7. Is there something
> blatently obvious that I'm doing wrong? (I know I need timeouts instead
> of infinite while loops.) Currently this code does not write anything
> to the EEPROM.
>
> void write_eeprom( uint16_t addr, uint16_t data)
> {
> uint16_t *sectorBaseAddr;
> uint16_t loWord;
> uint16_t hiWord;
> uint16_t tickNow;
> uint8_t eepromStatus;
>
> if ( ECLKDIV | ECLKDIV_EDIVLD_MASK )
> {
> while( !(ESTAT & ESTAT_CBEIF_MASK) );
>
> if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
> {
> ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
> }
> //*********************************************************************
> // Preserve other bytes in sector
>
> //*********************************************************************
>
> /* Get the base address of the sector to erase */
> sectorBaseAddr = (uint16_t *)(addr & ~0x03);
>
> if ( !( sectorBaseAddr >= (uint16_t *)0xE00 && sectorBaseAddr <
> (uint16_t *)0xF00 ) )
> {
> pet_watchdog();
> return;
> }
>
> /* Preserve the current sector contents */
> loWord = sectorBaseAddr[0];
> hiWord = sectorBaseAddr[1];
> //*********************************************************************
> // Determine which word the new data occupies
>
> //*********************************************************************
> if((addr & 0x02) == 0)
> {
> loWord = data;
> }
> else
> {
> hiWord = data;
> }
>
> /* Write first word */
> sectorBaseAddr[0] = loWord;
> ECMD = EEPROM_CMD_SECTOR_MODIFY;
> ESTAT |= ESTAT_CBEIF_MASK;
> while ( !(ESTAT & ESTAT_CCIF_MASK) );
>
> /* write second word */
> while( !(ESTAT & ESTAT_CBEIF_MASK) );
> if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
> {
> ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
> }
> /* Write second word */
> sectorBaseAddr[1] = hiWord;
> ECMD = EEPROM_CMD_WORD_PROGRAM;
> ESTAT |= ESTAT_CBEIF_MASK;
> while ( !(ESTAT & ESTAT_CCIF_MASK) );
>
> /* write second word */
>
> while( !(ESTAT & ESTAT_CBEIF_MASK) );
>
> if ( ESTAT & (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK) )
> {
> ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK);
> }
> }
> /* Reset the watchdog */
> pet_watchdog();
>
> } // end of write_eeprom
> Programmers work long hours trying to design stuff that keeps them from
> having to work long hours. -David Allen "Making It All Work"
>
> Joseph Tennies
>
> Senior Software Engineer
>
> Esterline Control Systems - AVISTA
>
>
>

The 2024 Embedded Online Conference