Erase flash sector on MK70FX512VMJ15

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Erase flash sector on MK70FX512VMJ15

跳至解决方案
1,756 次查看
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 解答
1,036 次查看
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 回复数
1,037 次查看
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 项奖励
回复
1,036 次查看
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 项奖励
回复
1,036 次查看
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 项奖励
回复
1,036 次查看
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

};