FLASH Reprogramming on S12X

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

FLASH Reprogramming on S12X

10,815 Views
ThomasG
Contributor I

Are there any plans for a FLASH programming utility app note (much like AN2720) to be created and released specific to the S12X.  I am working with a MC9S12XDP512 and would like to have the capability of reprogramming a few pages of FLASH that contain data tables.

I think I understand the basic setup of the FLASH registers along with address and data lines but don't fully understand the assembly code in AN2720.  Is the stack being used to basically check the CBEIF for the flash complete signal because the FLASH cannot be read from at this time meaning RAM has to be used.  Can this assembly code be used as is on an S12X core?

Also, if the XGATE is configured to run out of RAM, could 1 of the 8 software trigger interrupt routines be used after the FLASH command is sent to the fcmd register.  This would eliminate the need to specifically use the stack.  Any feedback on any of these questions is appreciated.

Thanks,

Thomas

Labels (1)
0 Kudos
14 Replies

1,457 Views
Technoman64
Contributor III
I have used the following code to erase FLASH sectors and re-program for 1024 byte data arrays.
 
You can call the functions from FLASH as long as the calling functions are NOT in same FLASH Block as the Page that is being erased and programmed.
 
There are 2 FALSH blocks in the 256k device and 4 inthe 512k device. This method will NOT work on a device with less than 256k of FLASH.
 
This is for the (X) parts only! This will NOT work on a standard HCS12 device!
 
You must use Global FAR addressing

/* FLASH data table address range */

#define TABLE_ADDRESS_LOW 0x780000

#define TABLE_ADDRESS_HIGH 0x783FFF

Not sure if this is what you are looking for. This did allow me to store larger data tables in FLASH though.

Code I used

Code:

#pragma DATA_SEG FlashCtrl_DATA                                            #pragma CODE_SEG FlashCtrl_CODE                     /* FlashCtrl_WriteWord */BYTE FlashCtrl_WriteWord(WORD *__far WriteAddress, WORD Data){ /* Check range of WriteAddress */ if(WriteAddress < (WORD *__far)TABLE_ADDRESS_LOW || WriteAddress > (WORD *__far)TABLE_ADDRESS_HIGH)  return FALSE;  /* Has the FLASH divider clock been set— */ if(!FCLKDIV_FDIVLD)  FlashCtrl_Init();  /* Check command flag */ if(!FSTAT_CBEIF)  return FALSE;  /* Clear flags */ FSTAT = 48;    /* Array address and program data */   WriteAddress[0] = Data;    /* Word program command */ FCMD = 32;    /* Clear flag command buffer empty */    FSTAT = 128;     /* Is protection violation or acces error detected– */   if ((FSTAT_PVIOL == 1)||(FSTAT_ACCERR == 1))     return FALSE;      /* Wait to buffer empty */ while(FSTAT_CBEIF == 0); /* Wait to command complete */ while(FSTAT_CCIF == 0); /* Was write successful˜ */ if(WriteAddress[0] != Data)  return FALSE;  /* Return success */  return TRUE;}/* FlashCtrl_EraseSector */BYTE FlashCtrl_EraseSector(WORD *__far EraseAddress){ /* Check range of EraseAddress */ if(EraseAddress < (WORD *__far)TABLE_ADDRESS_LOW || EraseAddress > (WORD *__far)TABLE_ADDRESS_HIGH)  return FALSE;  /* Has the FLASH divider clock been set™ */ if(!FCLKDIV_FDIVLD)  FlashCtrl_Init();  /* Check command flag */ if(!FSTAT_CBEIF)  return FALSE;  /* Clear flags */ FSTAT = 48;  /* Write to erase address */ EraseAddress[0] = 0x10;   /* Initiate Sector Erase commamd */ FCMD = 64; /* Clear flag command buffer empty */ FSTAT = 128;        /* Is protection violation or access error detected ? */ if ((FSTAT_PVIOL == 1)||(FSTAT_ACCERR == 1))     /* If yes then error */     return FALSE;        /* Wait to buffer empty */   while(FSTAT_CBEIF == 0); /* Wait to command complete */ while(FSTAT_CCIF == 0);  /* Return success */ return TRUE;}/* FlashCtrl_Init */void FlashCtrl_Init(void){#if OSC_SPEED == 4000000 /* 4mhz clock */ FCLKDIV = 20;                        #else if OSC_SPEED == 10000000 /* 10mhz clock */ FCLKDIV = 50;#endif}#pragma DATA_SEG DEFAULT                                            #pragma CODE_SEG DEFAULT                     


 

0 Kudos

1,457 Views
jmv
Contributor I

I am trying to write some code in C to do a mass erase and program of the flash for a 9S12X.

I have declared a pointer to the flash:

 

typedef uint16_t * far Flash_TAddress;

During the process I increment this address to point to the next block. The Code W\rrior compiler treats it as a 14-bit effective address, so when I try to add 0x4000 to it it effectively adds 0 and produces no code. This is presumable becuse it teats the address as an effective address used with the PPAGE register.

 

I have done some experiments to see what code the compiler produces, and it seems to use a mixture of GPAGE and PPAGE, as shown in the following snippet:

 

 

static uint32_t * far dq;

 

  dq = (Flash_TAddress)0xE0;

  *dq = 12;

  dq = dq + 0x4000L;
 
  *dq = 23;

 

The compiler assembly output for this is:

 

  228:    dq = (Flash_TAddress)0xE0;
  0001 c6e0         [1]     LDAB  #224
  0003 87           [1]     CLRA  
  0004 7c0000       [3]     STD   dq:1
  0007 7a0000       [3]     STAA  dq
  229:  
  230:    *dq = 12;
  000a fe0000       [3]     LDX   dq:1
  000d f60000       [3]     LDAB  dq
  0010 5b10         [2]     STAB  /*GPAGE*/16
  0012 c7           [1]     CLRB  
  0013 186c00       [3]     GSTD  0,X
  0016 c60c         [1]     LDAB  #12
  0018 186c02       [3]     GSTD  2,X
  231:  
  232:    dq = dq + 0x4000L;
  233:    
  234:    *dq = 23;
  001b c7           [1]     CLRB  
  001c 186c00       [3]     GSTD  0,X
  001f c617         [1]     LDAB  #23
  0021 186c02       [3]     GSTD  2,X

 

So it uses GPAGE for assigning the pointer and storing the 12, but assumes PPAGE when I add 0x4000 to it.

 

How do I get the compiler o incremement the address and automatically increment PPAGE, or can I not do this? If not, how do I do what I am trying to do, i.e. erase the flash?

 

The compiler version is Code WArrior of rS12X version 4.7, with command line compiler chc12 version 5.0.35 build 8093.

 

Thanks

 

0 Kudos

1,457 Views
kef
Specialist I

Try replacing far with __far24. __far GPAGE pointer +- update only lower 16bits of pointer. __far24 updates all bits. Or maybe convert __far pointer to long, add/subtract and finally convert long back into __far pointer.

0 Kudos

1,457 Views
jmv
Contributor I

Thanks for your suggestions. I have been busy with a few other things so have not got round to this.

 

I have set up the PPAGE register and written to a dummy address within the block as the data sheet suggests. In this way I can use 16-bit addresses and everything seems to work OK.

 

Thanks

0 Kudos

1,457 Views
kef
Specialist I

dq is a pointer to uint_32t. So when you add 0x4000 to dq, pointer address should increment by 0x4000*sizeof(uint_32t). Thats + 0x10000 and not the size of PPAGE.

0 Kudos

1,457 Views
ThomasG
Contributor I
Thanks, Technoman for your reply.  The information of being able to reprogram one block while accessing code from another block is what I needed.  I read in the Data Sheet that a FLASH couldn't be accessed while a FLASH command was executed in that block but didn't think about how there are 4 blocks on the DP512 part.
 
Thanks again.
0 Kudos

1,457 Views
sbsmt
Contributor I

i'm using trying to program a p-flash sector of 1024 bytes on a s12xet256.

all works well in the adddress space (0x00780000-0x0079FFFF),(0x007E0000-0x007F3FFF) and  (0x007F8000-0x007FBFFF) but if I try to program and erase sectors in the spaces (0x007F4000-0x007F7FFF) and (0x007FC000-0x007F7F00) the program jumps to strange address and don't program the memory

my code is placed in  0x007F4000-0x007F7FFF

 

someone have the same problem or could help me?

tanks

0 Kudos

1,457 Views
kef
Specialist I

Flash block is not readable while any flash command is in progress (in this flash block). Also not readable while you are applying backdoor unsecure key (KEYACC bit is set). This means CPU can't read memory and runs away. Also CPU can't read interrupt vectors from flash block being programmed.

Your flash routines should be placed to and run from RAM.

0 Kudos

1,457 Views
sbsmt
Contributor I

tanks!

I'm using this code to write a block in PFlash.

if I break(with 2 breakpoints) at the executions "while (FSTAT_CCIF == 0);" it writes in memory the data otherwise if the program runs it jumps away.

how can I modify to correct this function?

 

 

static byte flashpxWriteBlock(dword Addr, word From, word To, word* Data)
{
  byte err = 0;
  word i;
  byte j;
  dword PhraseAddr;

  if(From == To) {
    return ERR_OK;
  }
  i = From;
  PhraseAddr = (dword)Addr;
  while(i < To) {
  // FSTAT: ACCERR=1,FPVIOL=1
    FSTAT = 0x30;                      
    FCCOBIX = 0;                       
    FCCOBHI = FLASHCMD_PROGRAM;        
    FCCOBLO = (byte)(PhraseAddr >> 16);
    FCCOBIX++;                         
    FCCOB = (word)PhraseAddr;          
    for(j = 0;j < 8;j+=2) {
      FCCOBIX++;                       
      FCCOB = *(word*)(Data + i/2);    
      i+=2;
      if(i >= To) {break;}
    }
    FSTAT = 128;                       
    if (i < To) {                      
      while (FSTAT_CCIF == 0);         
      if ((FSTAT_FPVIOL == 1) || (FSTAT_ACCERR == 1)) {
        return ERR_NOTAVAIL;           
      }
      if (FSTAT_MGSTAT) {              
        err = 1;                       
      }
    }
    PhraseAddr +=8;
  }
  if (bFlashpxWait) {                  
    while (FSTAT_CCIF == 0);           
    if ((FSTAT_FPVIOL == 1) || (FSTAT_ACCERR == 1)) {
      return ERR_NOTAVAIL;             
    }
    if (FSTAT_MGSTAT) {                
      err = 1;                         
    }
  }
  if(err) {
    return ERR_VALUE;                  
  }
  return ERR_OK;                       
}
0 Kudos

1,457 Views
kef
Specialist I

Just move your flash routines to RAM. Search box at the bottom of this page can give many possible answers. One of results:

 

http://forums.freescale.com/freescale/board/message?board.id=16BITCOMM&message.id=6966&query.id=1569...

0 Kudos

1,457 Views
sbsmt
Contributor I
tanks!
0 Kudos

1,457 Views
Steve
NXP Employee
NXP Employee


Also, if the XGATE is configured to run out of RAM, could 1 of the 8 software trigger interrupt routines be used after the FLASH command is sent to the fcmd register.  This would eliminate the need to specifically use the stack.  Any feedback on any of these questions is appreciated.

Using the XGATE wouldn't solve the basic problem of the CPU having a valid program store. As soon as the XGATE enabled the flash programming state machine the CPU would lose its program space and disappear into the void. The CPU has to be running in an unaffected block when the FSTAT register is written.
S12X does have some benefits that can be brought to bear but they would impact the overall simple structure here. Specifically, you can move the CPU's vector table and/or have XGATE handle the interrupts while the reprogramming is taking place. The best approach in using these features would depend on how much functionality you needed to have while reprogramming was taking place.
Looking to the future we will have another option on the S12XE which allows the XGATE to reprogram the flash too. Obviously again the CPU would have to be operating in a known safe condition before this could be used.
0 Kudos

1,457 Views
J2MEJediMaster
Specialist I

Application note AN2548 describes a HCS12-based serial monitor with some basic debugging operations and writing to flash. Probably overkill for you, but still an excellent source of information. The source code is in two separate archive files and is in assembly, but is heavily commented. I'm going to attach these files here to save you the trouble of tracking them down.

In regard to your other questions:

1) The HC12S instructions should run on a S12X core, but you may have to modify the programming logic to make it work with the S12X's memory map.

2) I don't know anything about the XGATE and so can't answer to that.

3) When you're programming Flash, it's usually a really good idea to disable interrupts, since an interrupt is going to take the CPU to a routine in Flash, which happens to be what you're trying to modify. Barring that, the interrupt can also disrupt the precise sequence of writes required to program the Flash.

---Tom

 

http://www.freescale.com/files/microcontrollers/doc/app_note/AN2548.pdf

Message Edited by t.dowe on 2009-09-11 03:07 PM
0 Kudos

1,457 Views
ThomasG
Contributor I
Thank you for the reply.
 
I guess I should have qualified the use of the XGATE as saying the XGATE code, data, and vector table are all loaded into RAM coming out of reset.  Because I believe it fully runs out of RAM, that is why I thought it could be used but I will look at the app. note you provided.
 
I am trying to step through AN2720 currently.  I think the problem I am having is that I want to use the global addressing scheme provided on the S12X but the routines were written for the S12 core and make use of the FLASH paging scheme.
 
Thanks.
0 Kudos