HCS12XEQ384 - Internal Flash - Programming (S12XFTM384K2V1)

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

HCS12XEQ384 - Internal Flash - Programming (S12XFTM384K2V1)

1,077件の閲覧回数
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

ラベル(1)
0 件の賞賛
返信
4 返答(返信)

874件の閲覧回数
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 件の賞賛
返信

874件の閲覧回数
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

874件の閲覧回数
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 件の賞賛
返信

874件の閲覧回数
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 件の賞賛
返信