Erase flash sector on MK70FX512VMJ15

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

Erase flash sector on MK70FX512VMJ15

ソリューションへジャンプ
1,580件の閲覧回数
lucaiser
Contributor III

Hi friends.

I'm working on a kinetis MK70FX512VMJ15 and IAR Embedded workbench for ARM (version 6.30.4). I'm writing a flash driver for this device.

I have a problem with erase flash sector command. When i try to launch this command in debug with J-Link, this command is able to erase only few sectors on Program Flash Memory. With some sectors this command doesn't have success but i have no errors in FTFE_FSTAT register (value 0x80). I can't understand why seems to be not possible to erase some of this sectors.

Notice that i execute command from RAM memory as explained in AN4695 and i have also verified ssd attached to this application note. I have no protection set in FTFE_FPROT (value 0xFF).

I can't understand where i'm wrong, i hope you have any idea.

Many thanks for now, bye.

タグ(3)
0 件の賞賛
返信
1 解決策
860件の閲覧回数
lucaiser
Contributor III

I've solved this problem. It was a mistake of "view memory" window of IAR Embedded Workbench IDE.

I have tried to read erased memory location copying its content in a variable and i see 0xFF as expected.

Thanks for your help, i have another question but i prefer to open a new topic.

Best regards.

元の投稿で解決策を見る

0 件の賞賛
返信
4 返答(返信)
861件の閲覧回数
lucaiser
Contributor III

I've solved this problem. It was a mistake of "view memory" window of IAR Embedded Workbench IDE.

I have tried to read erased memory location copying its content in a variable and i see 0xFF as expected.

Thanks for your help, i have another question but i prefer to open a new topic.

Best regards.

0 件の賞賛
返信
860件の閲覧回数
mjbcswitzerland
Specialist V

Hi

Erasing program flash in all KL and K devices is the same (apart from sector size). A driver should not be compiler dependent (I use one which works with GCC, CW, IAR, Keil and Rowley).

Check how you are setting the sector to be erased and also ensure that the address is phrase aligned ([2:0] = 0), eg:

    FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash
    FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);
    FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);

If the problem continues please post the erasing code so that it can be checked.

Regards

Mark

0 件の賞賛
返信
860件の閲覧回数
lucaiser
Contributor III

Thank you Mark, here you can find the source code of my driver:

#define FLASH_ERASE_SECTOR_CMD_LEN                4  

#define FLASH_CMD_OFFSET                                      0

#define FLASH_CMD_ADDRESS_23_16_OFFSET          1

#define FLASH_CMD_ADDRESS_15_08_OFFSET          2

#define FLASH_CMD_ADDRESS_07_00_OFFSET          3

#define FTFE_ERASE_SECTOR                                    (UBYTE)0x09

void vFlashInit( void )

{

  while( ( FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK ) == 0 )

  {

    /* Wait until CCIF is set */

  }

  FTFE_FSTAT |= FTFE_FSTAT_RDCOLERR_MASK | FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK;

}

void vTestEraseFlashSector( void )

{

  UBYTE ubCommandArray[ FLASH_ERASE_SECTOR_CMD_LEN ];

  ULONG ulDestinationAddress;

  UBYTE ubIndex;        

  ulDestinationAddress = (ULONG)0x00001000;

  /* Build command */

  ubCommandArray[ FLASH_CMD_OFFSET ]                = FTFE_ERASE_SECTOR;

  ubCommandArray[ FLASH_CMD_ADDRESS_23_16_OFFSET ]  = (UBYTE)( ulDestinationAddress >> 16 );

  ubCommandArray[ FLASH_CMD_ADDRESS_15_08_OFFSET ]  = (UBYTE)( ulDestinationAddress >> 8 );

  ubCommandArray[ FLASH_CMD_ADDRESS_07_00_OFFSET ]  = (UBYTE)( ulDestinationAddress );

  

  /* Copy to FCCOBx */

  for( ubIndex = 0; ubIndex < FLASH_ERASE_SECTOR_CMD_LEN; ubIndex++ )

  {

    while( ( FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK ) != FTFE_FSTAT_CCIF_MASK )

    {

        /* Attende fino a che trova il bit settato */

    }

    wvSetFCCOBxValue( ubIndex, ubCommandArray[ ubIndex ] );

  }

  /* Launch command */

  wenFlashLaunchCommand();

}

static void wvSetFCCOBxValue( UBYTE ubRegIndex, UBYTE ubRegValue )

{

  switch( ubRegIndex )

  {

  case 0:

    FTFE_FCCOB0 = ubRegValue;

    break;

  

  case 1:

    FTFE_FCCOB1 = ubRegValue;

    break;  

  case 2:

    FTFE_FCCOB2 = ubRegValue;

    break;  

  case 3:

    FTFE_FCCOB3 = ubRegValue;

    break;  

  case 4:

    FTFE_FCCOB4 = ubRegValue;

    break;  

  case 5:

    FTFE_FCCOB5 = ubRegValue;

    break;  

  case 6:

    FTFE_FCCOB6 = ubRegValue;

    break;  

  case 7:

    FTFE_FCCOB7 = ubRegValue;

    break;  

  case 8:

    FTFE_FCCOB8 = ubRegValue;

    break;  

  case 9:

    FTFE_FCCOB9 = ubRegValue;

    break;  

  case 10:

    FTFE_FCCOBA = ubRegValue;

    break;  

  case 11:

    FTFE_FCCOBB = ubRegValue;

    break;  

  default:

    break;

  }

}

static __ramfunc EN_DIAGNCODE wenFlashLaunchCommand( void )

{

  FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;

  /* Check CCIF flag */

  while( ( FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK ) != FTFE_FSTAT_CCIF_MASK )

  {

      /* Wait until CCIF is set */

  }

  return EN_DIAGNCODE_OK;

}

In main application i call first vFlashInit and then vTestEraseFlashSector. Status register is OK (value 0x80) but flash memory seems to be unchanged.

Many thanks, bye.

0 件の賞賛
返信
860件の閲覧回数
mjbcswitzerland
Specialist V

Hi

Try

FTFE_FSTAT = FTFE_FSTAT_CCIF_MASK;

instead of

FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;

Regards

Mark

P.S As reference I use the following code for deleting a sector. Your code is essentially doing the same but is rather more difficult to read. I don't see any need to check the status after every command write.

Note that I also use protect the flashing code from interrupts and use machien code for the flash routine (since it is so simple and it avoids compiler optimisation difficulties where some compilers want to in-line the routine).

while (!(FTFL_FSTAT & FTFL_STAT_CCIF)) {}                        // wait for previous commands to complete
if (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL)) {        // check for errors in previous command
FTFL_FSTAT = (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL);          // clear old errors

}

FTFL_FCCOB0 = FCMD_ERASE_FLASH_SECTOR;

FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash

FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);

FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);

uDisable_Interrupt();                                            // protect this region from interrupts
fnRAM_code((volatile unsigned char *)FTFL_BLOCK);                // execute the command from SRAM
uEnable_Interrupt();                                             // safe to accept interrupts again

return (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_MGSTAT0)); // if there was an error this will be non-zero

static unsigned short fnFlashRoutine[] = {                           // to avoid potential compiler in-lining of the routine (removing position independency) the machine code is used directly
0x2180,// MOVS   r1,#0x80                                       load the value 0x80 (command complete interrupt flag) to register r1
0x7001,// STRB   r1,[r0,#0x00]                                  write r1 (0x80) to the passed pointer location (r0)
0x7801,// LDRB   r1,[r0,#0x00]                                  read back from the same location to r1
0x0609,// LSLS   r1,r1,#24                                      shift the register content by 24 bits to the left so that the command complete interrupt flag is at bit 31
0xd5fc,// BPL-4                                             if the command complete interrupt flag bit is '0' (register content is not negative value) branch back to read its value again
0x4770 // BX lr                                             return from sub-routine

};