Programming Flash, FADDR - MC9S12DG256

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Programming Flash, FADDR - MC9S12DG256

3,665 Views
HenryL
Contributor III
I'm writing a bootloader to program flash. I know the three main registries that I need are:
FADDR - 16bit address of where flash data should be written to
FDATA - 16bit data of flash
FCMD - 8bit command to write/erase the flash

My question is, according to the datasheet, bit 15 of FADDR is not writable, which means I can only write flash locations mapped at 0x0000 to 0x7FFF. How can I write to the rest of the memory?

I am using HCS12 dg256



Message Edited by Henry L on 2008-12-08 06:53 PM

 

Added p/n to subject.



Message Edited by NLFSJ on 2008-12-16 09:52 PM
Labels (1)
0 Kudos
9 Replies

1,025 Views
HenryL
Contributor III
kef,

i must kindly ask for your help again. I have been succesful at writing to flash. However, I am now having trouble writing to eeprom.

the following is my code:
Code:
char FchrEepromWrite (unsigned char *PAuchrCanData){ unsigned char LuchrBankNum = 0; unsigned char LuchrReturn = 0; unsigned char LuchrIndex = 0; unsigned char LuchrDone = 0; int * LptrWriteAddr; //initialize commands //clear errors if (ESTAT & (PVIOL | ACCERR))  ESTAT |= (PVIOL | ACCERR);   //wait for cmd registries to be empty and ready to take new cmds while(!(ESTAT & CBEIF)); while(!LuchrDone) {  switch(LuchrIndex)  {  case 0:   LptrWriteAddr = (int *)((PAuchrCanData[1] << 8) | PAuchrCanData[2]);   ECMD = defEeCmdSectErase;   break;  case 1:   LptrWriteAddr = (int *)((PAuchrCanData[1] << 8) | PAuchrCanData[2]);   *LptrWriteAddr = (PAuchrCanData[3] << 8) | PAuchrCanData[4];   ECMD = defEeCmdProgram;   break;  case 2:   LptrWriteAddr = (int *)(((PAuchrCanData[1] << 8) | PAuchrCanData[2]) + 2);   *LptrWriteAddr = (PAuchrCanData[5] << 8) | PAuchrCanData[6];   ECMD = defEeCmdProgram;   break;  }  ESTAT |= CBEIF;  if (ESTAT & PVIOL)  {   ESTAT |= PVIOL;   LuchrDone = 1;  }  else if (ESTAT & ACCERR)  {   ESTAT |= ACCERR;   LuchrDone = 1;  }  else  {   while (!(ESTAT & CBEIF));   while (!(ESTAT & CCIF));   LuchrIndex++;   if (LuchrIndex > 2)   {    LuchrDone = 1;    LuchrReturn = 1;   }  } } return LuchrReturn;}

I am communicating via CAN. The 8 bytes of CAN data gets passed into this function, where bytes 1&2 form the addr of the EE, and bytes 3,4,5&6 form are the data. This function is a three step process. First I erase the 2 word (4 byte) sector. Then I write the two words in one at a time. However, it is not working. For sectors that are already erased (ie 0xFFFF) it works, but sectors that aren't, results are unpredictable. Am I not erasing properly? I made sure the address I'm specifying is aligned correctly.

Thanks!


Message Edited by Henry L on 2008-12-15 07:29 PM

Message Edited by Henry L on 2008-12-15 07:32 PM
0 Kudos

1,025 Views
kef
Specialist I
I see that you are clearing ESTAT flags wrong way, but I'm not sure if this is what makes your code not working. My advice is first fix these bugs, then let us know if it fixes problems or not. What's wrong with flags:
 
When you do   ESTAT |= (PVIOL | ACCERR);  , you write ones not only to PVIOL and ACCERR, but also to CBEIF, because CBEIF is most probably set already. Actually you want to clear error flags, but in reality you are trying to start some EEPROM command. I hope you understand that. Either do
 
ESTAT = PVIOL | ACCERR;
 
or
 
ESTAT &= PVIOL | ACCERR;
 
Please fix marked lines
Code:
char FchrEepromWrite (unsigned char *PAuchrCanData){ unsigned char LuchrBankNum = 0; unsigned char LuchrReturn = 0; unsigned char LuchrIndex = 0; unsigned char LuchrDone = 0; int * LptrWriteAddr; //initialize commands //clear errors if (ESTAT & (PVIOL | ACCERR)) ESTAT |= (PVIOL | ACCERR);   //wait for cmd registries to be empty and ready to take new cmds while(!(ESTAT & CBEIF)); while(!LuchrDone) {  switch(LuchrIndex)  {  case 0:   LptrWriteAddr = (int *)((PAuchrCanData[1] << 8) | PAuchrCanData[2]);   ECMD = defEeCmdSectErase;   break;  case 1:   LptrWriteAddr = (int *)((PAuchrCanData[1] << 8) | PAuchrCanData[2]);   *LptrWriteAddr = (PAuchrCanData[3] << 8) | PAuchrCanData[4];   ECMD = defEeCmdProgram;   break;  case 2:   LptrWriteAddr = (int *)(((PAuchrCanData[1] << 8) | PAuchrCanData[2]) + 2);   *LptrWriteAddr = (PAuchrCanData[5] << 8) | PAuchrCanData[6];   ECMD = defEeCmdProgram;   break;  } ESTAT |= CBEIF;  if (ESTAT & PVIOL)  {  ESTAT |= PVIOL;   LuchrDone = 1;  }  else if (ESTAT & ACCERR)  {  ESTAT |= ACCERR;   LuchrDone = 1;  }  else  {   while (!(ESTAT & CBEIF));   while (!(ESTAT & CCIF));   LuchrIndex++;   if (LuchrIndex > 2)   {    LuchrDone = 1;    LuchrReturn = 1;   }  } } return LuchrReturn;}

 


Message Edited by kef on 2008-12-16 09:29 AM
0 Kudos

1,025 Views
HenryL
Contributor III
i made those changes. still a no go. results are the same. EE that are already erased, I can write fine. EE that aren't, i get jibberish. The resulting values are neither the old nor new.
0 Kudos

1,025 Views
HenryL
Contributor III
update:
got it working! turns out that when I erase, not only do i need to assign an address to my variable LptrWriteAddr, I also have to assign data to it. My guess is that that's how the micro/compiler knows to put it in the cmd buffer eventhough data is not used on an erase command. So all i did was add one more line to my erase case.

Code:
case 0:
 LptrWriteAddr = (int *)((PAuchrCanData[1] << 8) | PAuchrCanData[2]);
 *LptrWriteAddr = 0;
 ECMD = defEeCmdSectErase;
 break;

 


Message Edited by Henry L on 2008-12-16 01:33 PM
0 Kudos

1,025 Views
kef
Specialist I
From the docs:
 

In normal modes, the FADDR (FADDRHI, FADDRLO) register reads zeros and is not writable.

Instead of using FADDR and FDATA, as docs say, you should

...Write the aligned data word to be programmed to the valid Flash address space. The address and data will be stored in internal buffers...

 

0 Kudos

1,025 Views
HenryL
Contributor III
so what is FADDR and FDATA used for, if anything at all?


"Write the aligned data word to be programmed to the valid Flash address space. The address and data will be stored in internal buffers..."

Meaning I should do something like this?
unsigned int * Pointer = 0x8000;
*Pointer = WordOfFlashData;
FCMD = 0x20;
FSTAT |= CBEIF;

with FADDR & FDATA, you had to write 2 bytes (a word) of data at a time, no more no less. Does this still hold true using this method?


And while we're on the subject, is writing to eeprom similar?


Message Edited by Henry L on 2008-12-09 11:36 AM
0 Kudos

1,025 Views
kef
Specialist I


Henry L wrote:
so what is FADDR and FDATA used for, if anything at all?
You can use them for example to program flash in special single chip mode using BDM pod. You can't run in special mode without BDM.
 
"Write the aligned data word to be programmed to the valid Flash address space. The address and data will be stored in internal buffers..."

Meaning I should do something like this?
unsigned int * Pointer = 0x8000;
*Pointer = WordOfFlashData;
FCMD = 0x20;
FSTAT |= CBEIF;
Yes. But also keep in mind that flash and EEPROM are not readable while CCIF bit is 0. Not readable memory means also that CPU can't execute code from memory you are programming. Also CPU can't fetch interrupt vectors from flash array being progammed / erased. Your flash programming routines should run from RAM, EEPROM, another flash array (on D256 you have 4 flash arrays), or external memory.

with FADDR & FDATA, you had to write 2 bytes (a word) of data at a time, no more no less. Does this still hold true using this method?
 
You should find flash program and erase algorithms in the docs.



And while we're on the subject, is writing to eeprom similar?
 
Yes.


0 Kudos

1,025 Views
HenryL
Contributor III


kef wrote:

Yes. But also keep in mind that flash and EEPROM are not readable while CCIF bit is 0. Not readable memory means also that CPU can't execute code from memory you are programming. Also CPU can't fetch interrupt vectors from flash array being progammed / erased. Your flash programming routines should run from RAM, EEPROM, another flash array (on D256 you have 4 flash arrays), or external memory.
I will running code from RAM. I'm implementing something similar to the app notes for LRAE & LFAE.

You should find flash program and erase algorithms in the docs.
If you are referring to the FTS256K block guide, then yes, it seems that I do have to write one word at a time, allowing the CBEIF to trigger before continuing.

Also, according to Fig4-2 of that document, after I launch the command, I should wait for CBEIF to be set before writing the next word. Should not also be waiting for CCIF for the command to complete, before writing the next word?
0 Kudos

1,025 Views
kef
Specialist I


Henry L wrote:

Also, according to Fig4-2 of that document, after I launch the command, I should wait for CBEIF to be set before writing the next word. Should not also be waiting for CCIF for the command to complete, before writing the next word?
While programming many words, you don't have to wait for CCIF==1. But flash is not readable while FSTAT CCIF==0. So for example you can't verify what you programmed until CCIF==1.
0 Kudos