HCS12XEQ384 - Internal Flash - Programming (S12XFTM384K2V1)

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

HCS12XEQ384 - Internal Flash - Programming (S12XFTM384K2V1)

939 Views
saschapfengler
Contributor II

Hi there!

 

I'm having trouble programming words into the global address space.

Programming / Triggering of write operations shall be done "in the background" by utilising the "Command Status ISR".

First of all I used Processor Expert to generate FLASH1_Init() and added to it from there on.

 

As soon as FLASH1_Init() completes, the Command Status ISR is called non-stop.

Why is that? Do I need to disable Command Status Complete Interrupts within the ISR?

 

Now when I skip these ISRs by stepping during Debug, I call enHalFlashInternalWriteWord(), which sadly doesn't work either: When I reach "Schreiben einleiten" to initiate the programming (FSTAT |= FSTAT_CCIF_MASK;), ACCERR is still active, so setting CCIF (which should clear the flag) does nothing. (see attached file or code example)

 

Input Parameters: 0x7C0000 (Address), 0 (Data).

 

By the way: How does the Flash-Controller know, how many Words I want to program, starting with the Address?

For example: If I leave FCCOB3-5 empty, would the controller still attempt to write Zeros into the addresses related to FCCOB3-5?

 

Do I need to consider switching to program execution in RAM?

Is there a far easier way to program internal Flash that I am overlooking?

I tried to understand the "current" AN2720, however it appears to be outdated for S12XE / couldn't get it to work.

 

This is an excerpt from my code:

 

    /* Moegliche Fehler rücksetzen */

    FSTAT |= FSTAT_ACCERR_MASK + FSTAT_FPVIOL_MASK;

 

    /* FCCOB - Register vorbereiten */

    /** FCCOB0 */

    FCCOBIX  = 0u;

    FCCOB    = ((uint16)(((uint16)EN_P_FLASH_CMD_PROGRAM_P_FLASH) << 8)); /* Schreib-Kommando in FCCOB-MSB schreiben */

    FCCOB   |= (uint16)(u32ParAddrGlob >> 16);                            /* Oberste 7 Bit der glob. 23 Bit-Adresse  */

    /** FCCOB1 */

    FCCOBIX  = 1u;

    FCCOB    = (uint16)u32ParAddrGlob; /* Unterste 16 Bit der 23 Bit-Adresse */

    /** FCCOB2 */

    FCCOBIX  = 2u;

    FCCOB    = u16ParData;

 

    /* Schreiben einleiten */

    FSTAT |= FSTAT_CCIF_MASK;

 

    // Warten bis Schreiben abgeschlossen

    while(!M_BO_FLASH_CONTROLLER_IDLE);

 

    // Ergebnis stimmt nicht

    if((*far_pu16Dest) != u16ParData)

    {

      enRet = EN_HAL_RET_ERR_FLASH_DATA_INVALID;

    }

 

Thanks for Your time!

Original Attachment has been moved to: Flash_Internal.c.zip

Labels (1)
0 Kudos
4 Replies

736 Views
saschapfengler
Contributor II

Now it works.

It appears that you cannot put code into paged ram using pragmas.

If you debug, you see that the program changes the PPAGE-register-value to the ram-page number of your paged ram code section, once you reach your "ram function", which is wrong.

So what I did was to declare a part of the unpaged ram as Code-Section.

// PRM-File

       RAM                  = READ_WRITE    0x2000 TO   0x3BFF;

       RAM_CODE      = READ_WRITE    0x3C00 TO   0x3FFF;

     ...

  

      CODE_TEST         INTO  RAM_CODE;

0 Kudos

736 Views
iggi
NXP Employee
NXP Employee

Hi Sacha,

Nice that you work it out by yourself.

Just to leave some notes:

- we cannot read and write Flash from the same block at a time. Therefore during programming of a flash block, the command is usually executed from RAM (or other flash block if there is any)

- For the paged RAM, as it is written in .prm file - when using banked addressing for variable data, make sure to specify the option -D__FAR_DATA on the compiler command line (Alt+F7)

pastedImage_1.png

- Here you can download a pack of examples for S12XE device family where you can find CW project for Flash:
LAMA's S12XE unofficial examples

Regards,

iggi

736 Views
saschapfengler
Contributor II

Hey Iggi, thanks for your reply!

These examples are very enlightening. :smileywink:

I already had to activate the compiler command -D__FAR_DATA because of start-up code related warnings.

However, this does not change the behavior (meaning that PPAGE is being changed instead of RPAGE when entering the RAM-function).

This currently does not pose a problem, but in the future I might like to change RAM code to other pages / expand.

0 Kudos

736 Views
saschapfengler
Contributor II

First of all:

I got it to work, as long as I don't write into the same block from which the code is executed.

1) I disabled the CCIE in FCNFG, which stopped controller from being locked in an endless CMD-Status-Complete ISR.

2) FSTAT |= FSTAT_ACCERR_MASK + FSTAT_FPVIOL_MASK; was wrong for resetting Error Flags

-> FSTAT = FSTAT_ACCERR_MASK + FSTAT_FPVIOL_MASK; is correct (this way command execution is not triggered)

3) I now understand, that all 4 Words within the FCCOB-Register are written. No way around that.

The huge Problem I now face is this:

How do I get this Write-Function to work if the same Block, from which it is run, is being written to?

I tried to put the Code into RAM, simply by using #pragmas

However, when I get to debugging, the program stops the moment the "RAM-Function" is reached.

The current Test Code looks like this:

#pragma CODE_SEG CODE_TEST

/**

  Write Word, Word+1, Word+2, Word+3 into internal Flash starting at global Addr.

 

  @param[in] u32ParAddrGlob   -   Global Addr (Only even Addr. allowed)

  @param[in] u16Data          -   Data to be written

  @retval EN_HAL_RET_OK     -   Success

  @retval EN_HAL_RET_...    -   Error

*/

EN_HAL_RET enHalFlashInternalWriteWord(uint32 u32ParAddrGlob, uint16 u16ParData)

{

  EN_HAL_RET enRet = EN_HAL_RET_OK;

  uint16  u16Data = u16ParData;

  uint8   u8Ctr;

  uint16 *far far_apu16Dest[4];

  far_apu16Dest[0]  = (uint16 *far)u32ParAddrGlob;

  far_apu16Dest[1]  = (uint16 *far)(u32ParAddrGlob+2);

  far_apu16Dest[2]  = (uint16 *far)(u32ParAddrGlob+4);

  far_apu16Dest[3]  = (uint16 *far)(u32ParAddrGlob+6);

  /*|| Guard...*/

  if( ( M_BO_ADDR_ODD_U32(u32ParAddrGlob))    /* Ungerade Adresse uebergeben */

    /* Ziel-Speicher ist nicht geloescht */

    ||(!M_BO_FLASH_WORD_ERASED(far_apu16Dest[0]))

    ||(!M_BO_FLASH_WORD_ERASED(far_apu16Dest[1]))

    ||(!M_BO_FLASH_WORD_ERASED(far_apu16Dest[2]))

    ||(!M_BO_FLASH_WORD_ERASED(far_apu16Dest[3]))

    ||(!M_BO_FLASH_CONTROLLER_IDLE))          /* (Interner)Flashcontroller beschaeftigt */

  {

    enRet = EN_HAL_RET_ERR_GUARD;

  }

  /*...Guard ||*/

  /*|| Guard OK...*/

  else

  {

    /* Reset possible Flash-Errors */

    FSTAT = FSTAT_ACCERR_MASK + FSTAT_FPVIOL_MASK;

    /* FCCOB - Reg Preperations */

    /** FCCOB0 */

    FCCOBIX  = 0u;

    FCCOB    = ((uint16)(((uint16)EN_P_FLASH_CMD_PROGRAM_P_FLASH) << 8)); /* Write Command */

    FCCOB   |= (uint16)(u32ParAddrGlob >> 16);                            /* First 7 Bits of global 23 Bit-Addr.  */

    /** FCCOB1 */

    FCCOBIX  = 1u;

    FCCOB    = (uint16)u32ParAddrGlob; /* Lower 16 Bit of 23 Bit Addr. */

    /** FCCOB2 */

    FCCOBIX  = 2u;

    FCCOB    = u16Data;

    u16Data++;

    /** FCCOB3 */

    FCCOBIX  = 3u;

    FCCOB    = u16Data;

    u16Data++;

    /** FCCOB4 */

    FCCOBIX  = 4u;

    FCCOB    = u16Data;

    u16Data++;  

    /** FCCOB5 */

    FCCOBIX  = 5u;

    FCCOB    = u16Data;

    /* Initiate Write */

    FSTAT = FSTAT_CCIF_MASK;

    /* Wait till Write finished */

    while(!M_BO_FLASH_CONTROLLER_IDLE);

    /* Check Result (Reread) */

    for(u8Ctr = 0; u8Ctr < 4u; u8Ctr++)

    {

      /* Unexpected Value */

      if((*(far_apu16Dest[u8Ctr])) != (u16ParData + u8Ctr))

      {

        enRet = EN_HAL_RET_ERR_FLASH_DATA_INVALID;

      }

    }

  }

  /*...Guard OK ||*/

  return enRet;

}

#pragma CODE_SEG DEFAULT

///////////////////////////////////////////

.prm File

....

       RPAGE_FB      = READ_ONLY   0xFB1000 TO 0xFB1FFF;

....

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */

      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */

      STARTUP,                /* startup data structures */

      ROM_VAR,                /* constant variables */

      STRINGS,                /* string literals */

      NON_BANKED,             /* runtime routines which must not be banked */

      COPY              INTO  ROM_C000;

      DEFAULT_ROM       INTO  PAGE_FE, PAGE_FC, PAGE_FB, PAGE_FA, PAGE_F9, PAGE_F8, PAGE_F7, PAGE_F6,

                              PAGE_F5, PAGE_F4, PAGE_F3, PAGE_F2, PAGE_F1, PAGE_F0, PAGE_E7, PAGE_E6,

                              PAGE_E5, PAGE_E4, PAGE_E3, PAGE_E2, PAGE_E1, PAGE_E0;

      DEFAULT_RAM             /* all variables, the default RAM location */

                        INTO  RAM;

                       

      /*CODE_RAM               

                        INTO  RPAGE_FB;*/ /* Im RAM ablaufender Code */

                       

      CODE_TEST         INTO  RPAGE_FB;

END

////////////////////////////////

It seems like it does not make a difference, whether I deklare to Rampage als READ_WRITE or READ_ONLY

RPAGE_FB      = READ_WRITE   0xFB1000 TO 0xFB1FFF;

0 Kudos