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;