This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/RM48L952: F021 flash API does not operate in the same bank, resulting in a crash error

Part Number: RM48L952

Tool/software: Code Composer Studio

When using rm48 series processor to upgrade, flash API is needed to erase, read and write.

The overall process of upgrading is: when the program starts, it runs app directly. When communication command comes, it jumps to boot program, erases flash and writes new code.

The boot program is a separate project. The compiled binary code is placed in app in the form of an array, fixing the address of some functions, calling the function of boot from app through the function pointer, and realizing flash erasing, reading, writing and other functions.

If the flash operation in boot is executed in RAM, the binary code call in app that runs in RAM during code compilation does not run normally. Therefore, flash operation is not in RAM, that is, put boot in bank1 and app in bank0, so that the flash in boot can operate on the address in bank0. The specific address allocation is as follows:

The CMD file of bootloader:

MEMORY
{
    VECTORS    (X)   : origin=0x00180000 length=0x00000020

     FLASH0     (RX)  : origin=0x00180020 length=0x000fffff   

    SRAM       (RW)  : origin=0x08002000 length=0x0002D000
    STACK      (RW)  : origin=0x08000000 length=0x00002000
}
SECTIONS
{
   .intvecs : {} > VECTORS

   .text  > FLASH0
   .const > FLASH0
   .cinit > FLASH0
   .pinit > FLASH0
   .data  > SRAM
   .bss   > SRAM
}

App application CMD file:

MEMORY
{
    VECTORS (X)  : origin=0x00000000 length=0x00000020
    FLASH1  (RX) : origin=0x00000020 length=0x0017ffe0
    STACKS  (RW) : origin=0x08000000 length=0x00001500
    RAM     (RW) : origin=0x08001500 length=0x0003EB00
}
/*----------------------------------------------------------------------------*/
/* Section Configuration                                                      */
SECTIONS
{
    .intvecs : {} > VECTORS
    .text    : {} >  FLASH1
    .const   : {} > FLASH1
    .cinit   : {} > FLASH1
    .pinit   : {} > FLASH1
    .bss     : {} > RAM
    .data    : {} > RAM
    .sysmem  : {} > RAM
}

However, during the debugging process, it is found that running boot program separately in bank1 can erase the specified bank0 address, read and write operations are normal, and the results are correct after running for many times.

However, in the way described above, when calling the function in boot through function pointer from app, an error will be reported when calling several times in succession, which will directly result in flash ECC error, and the nerror indicator light will be on, which cannot be recovered.

Please help to see, what is the problem? What's the solution? Thank you!

  • Hello,

    You are right. For flash erase and program operations, the flash API has to be executed from a separate flash bank or SRAM. 

    When you program the application from bootloader, is the ECC calculated and programmed at the same time? When you call a function through an address, is this address programmed with valid ECC, or is it a blank address?

  • Thank you very much for your reply。

    When program the application from bootloader,I'm calling a function

    Fapi_issueProgrammingCommand((uint32_t *)dst, (uint8_t *)src, (uint32_t) bytes,0, 0, Fapi_AutoEccGeneration)

    Fapi_AutoEccGeneration,ECC is calculated automatically。

    When a function is called through an address, the address is not a blank address, but a valid address, 0x187900. However, this address should not be an ECC address, but a common address.

    I wonder if I am correct in saying this?

  • HI

    The following two figures show the register contents when ECC error occurs in simulation debugging

    Now the error of ECC live lock detect appears. I don't know how this error occurred?

    Can ECC be disabled?

    Looking forward to your reply!!!

  • Hello,

    Please refer to the sample code in TI bootloader: bl_flash.c (attached). This file has functions to erase/program flash using F021 flash APIs.

    The ECC checking should be disabled if you call flash blank check after erase operation. To disable the flash ECC check, please use the function defined in sys_core.asm: _coreDisableFlashEcc_()

    //*****************************************************************************
    //
    // bl_flash.c     : The file holds the main control loop of the boot loader.
    // Author         : QJ Wang. qjwang@ti.com
    // Date           : 9-19-2012
    //
    // Copyright (c) 2006-2011 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    //*****************************************************************************
    
    #include "bl_flash.h"
    #include "F021.h"
    #include "flash_defines.h"
    
    //uint32_t SYS_CLK_FREQ = 160;
    //#define APP_START_ADDRESS   0x100000
    
    //*****************************************************************************
    //
    // Returns the size of the ist sector size of the flash in bytes.
    //
    //*****************************************************************************
    uint32_t
    BLInternalFlashFirstSectorSizeGet(void)
    {
    	uint32_t firstSectorSize;
    	firstSectorSize = (uint32_t)(flash_sector[0].start) + flash_sector[0].length;
        return (firstSectorSize);
    }
    //*****************************************************************************
    //
    // Returns the size of the internal flash in bytes.
    //
    // This function returns the total number of bytes of internal flash in the
    // current part.  No adjustment is made for any sections reserved via
    // options defined in bl_config.h.
    //
    // \return Returns the total number of bytes of internal flash.
    //
    //*****************************************************************************
    uint32_t
    BLInternalFlashSizeGet(void)
    {
    	uint32_t flashSize;
    	flashSize = (uint32_t)flash_sector[NUMBEROFSECTORS-1].start + flash_sector[NUMBEROFSECTORS-1].length;
        return (flashSize);
    }
    
    //*****************************************************************************
    //
    //! Checks whether a given start address is valid for a download.
    //!
    //! This function checks to determine whether the given address is a valid
    //! download image start address given the options defined in bl_config.h.
    //!
    //! \return Returns non-zero if the address is valid or 0 otherwise.
    //
    //*****************************************************************************
    uint32_t
    BLInternalFlashStartAddrCheck(uint32_t ulAddr, uint32_t ulImgSize)
    {
        uint32_t count=0, i;
    
    	uint32_t ulWholeFlashSize;
    
        //
        // Determine the size of the flash available on the part in use.
        //
        ulWholeFlashSize = (uint32_t)flash_sector[NUMBEROFSECTORS-1].start + flash_sector[NUMBEROFSECTORS-1].length;  /* 3MB */
    
    	/* The start address must be at the begining of the sector */
        for (i = 0; i < NUMBEROFSECTORS; i++){
    		if ((ulAddr >= (uint32_t)(flash_sector[i].start)) && (ulAddr < ((uint32_t)flash_sector[i].start + flash_sector[i].length)))
    		{
    			count++;
    		}
    	}
        if (count == 0){
        	return(0);
        }
    
        //
        // Is the address we were passed a valid start address?  We allow:
        //
        // 1. Address 0 if configured to update the boot loader.
        // 2. The start of the reserved block if parameter space is reserved (to
        //    allow a download of the parameter block contents).
        // 3. The application start address specified in bl_config.h.
        //
        // The function fails if the address is not one of these, if the image
        // size is larger than the available space or if the address is not word
        // aligned.
        //
        if((
    #ifdef ENABLE_BL_UPDATE
                           (ulAddr != 0) &&
    #endif
                            (ulAddr != APP_START_ADDRESS)) ||
                           ((ulAddr + ulImgSize) > ulWholeFlashSize) ||
                           ((ulAddr & 3) != 0))
        {
        	return(0);
        }
        else  {
            return(1);
        }
    }
    
    
    uint32_t Fapi_BlockErase( uint32_t Bank, uint32_t ulAddr, uint32_t Size)
    {
    	uint8_t  i=0, ucStartBank, ucEndBank, ucStartSector, ucEndSector;
        uint32_t EndAddr, status;
    
    	EndAddr = ulAddr + Size;
    	for (i = 0; i < NUMBEROFSECTORS; i++){
    		if ((ulAddr >= (uint32_t)(flash_sector[i].start)) && (ulAddr < ((uint32_t)flash_sector[i].start + flash_sector[i].length)))
    		{
    			ucStartBank     = flash_sector[i].bankNumber;
    		    ucStartSector   = i;
    		    break;
    		}
    	}
    
    	for (i = ucStartSector; i < NUMBEROFSECTORS; i++){
    		if (EndAddr <= (((uint32_t)flash_sector[i].start) + flash_sector[i].length))
    		{
    			ucEndBank   = flash_sector[i].bankNumber;
    			ucEndSector = i;
    		    break;
    		}
    	}
    
    	status = Fapi_initializeFlashBanks((uint32_t)SYS_CLK_FREQ);   /* used for API Rev2.01 */
    
        for (i = ucStartBank; i < (ucEndBank + 1); i++){
            Fapi_setActiveFlashBank((Fapi_FlashBankType)i);
            Fapi_enableMainBankSectors(0xFFFF);                 /* used for API 2.01*/
            while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
        }
    
        for (i=ucStartSector; i<(ucEndSector+1); i++){
    		Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, flash_sector[i].start);
        	while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
        	while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
        }
    
        status =  Flash_Erase_Check((uint32_t)ulAddr, Size);
    
    	return (status);
    }
    
    //Bank here is not used. We calculate the bank in the function based on the Flash-Start-addr
    uint32_t Fapi_BlockProgram( uint32_t Bank, uint32_t Flash_Address, uint32_t Data_Address, uint32_t SizeInBytes)
    {
    	register uint32_t src = Data_Address;
    	register uint32_t dst = Flash_Address;
    	uint32_t buf[16] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x3a, 0x3bc};
    	uint32_t bytes;
    	uint32_t i=0;
    
    	if (SizeInBytes < 16)
    		bytes = SizeInBytes;
    	else
    		bytes = 16;
    
    	if ((Fapi_initializeFlashBanks((uint32_t)SYS_CLK_FREQ)) == Fapi_Status_Success){
    		 (void)Fapi_setActiveFlashBank((Fapi_FlashBankType)Bank);
    	     (void)Fapi_enableMainBankSectors(0xFFFF);                    /* used for API 2.01*/
    	}else {
             return (1);
    	}
    
    	while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
    	while( FAPI_GET_FSM_STATUS != Fapi_Status_Success );
    
        while( SizeInBytes > 0)
    	{
    		Fapi_issueProgrammingCommand((uint32_t *)dst,
    									 (uint8_t *)src,
    									 (uint32_t) bytes,
    									 0,
    									 0,
    									 Fapi_AutoEccGeneration);
    
            while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ){
               Fapi_issueProgrammingCommand(0x100100,
                                             &buf[0],
                                             16,
                                             0,
                                             0,
                                             Fapi_AutoEccGeneration);
                i++;
    
            }
    
    
     		while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
    
    		src += bytes;
    		dst += bytes;
    		SizeInBytes -= bytes;
            if ( SizeInBytes < 16){
               bytes = SizeInBytes;
            }
        }
    	return (0);
    }
    
    
    uint32_t Fapi_UpdateStatusProgram( uint32_t Bank, uint32_t Flash_Start_Address, uint32_t Data_Start_Address, uint32_t Size_In_Bytes)
    {
    	register uint32_t src = Data_Start_Address;
    	register uint32_t dst = Flash_Start_Address;
    	unsigned int bytes, status;
    
    	if (Size_In_Bytes < 16)
    		bytes = Size_In_Bytes;
    	else
    		bytes = 16;
    
    	Fapi_setActiveFlashBank((Fapi_FlashBankType)Bank);
    	Fapi_issueProgrammingCommand((uint32_t *)dst,
    									 (uint8_t *)src,
    									 (uint32_t) bytes,   //8,
    									 0,
    									 0,
    									 Fapi_AutoEccGeneration);
    
     	while( Fapi_checkFsmForReady() == Fapi_Status_FsmBusy );
    	status =  Flash_Program_Check(Flash_Start_Address, Data_Start_Address, Size_In_Bytes);
    	return (status);
    }
    
    
    
    uint32_t Flash_Program_Check(uint32_t Program_Start_Address, uint32_t Source_Start_Address, uint32_t No_Of_Bytes)
    {
    	register uint32_t *src1 = (uint32_t *) Source_Start_Address;
    	register uint32_t *dst1 = (uint32_t *) Program_Start_Address;
    	register uint32_t bytes = No_Of_Bytes;
    
    	while(bytes > 0)
    	{	
    		if(*dst1++ != *src1++)
    			return (1);   //error
    
    		bytes -= 0x4;
    	}
    	return(0);
    }	
    
    
    uint32_t Flash_Erase_Check(uint32_t Start_Address, uint32_t Bytes)
    {
    	uint32_t error=0;
    	register uint32_t *dst1 = (uint32_t *) Start_Address;
    	register uint32_t bytes = Bytes;
    
    	while(bytes > 0)
    	{	
    		if(*dst1++ != 0xFFFFFFFF){
    			error = 2;
    		}
    		bytes -= 0x4;
    	}
    	return(error);
    }
    
    
    
    uint32_t Fapi_BlockRead( uint32_t Bank, uint32_t Flash_Start_Address, uint32_t Data_Start_Address, uint32_t Size_In_Bytes)
    {
    	register uint32_t src = Data_Start_Address;
    	register uint32_t dst = Flash_Start_Address;
    	register uint32_t bytes_remain = Size_In_Bytes;
    	int bytes;
    
    	if (Size_In_Bytes < 16)
    		bytes = Size_In_Bytes;
    	else
    		bytes = 16;
    
     	while( bytes_remain > 0)
    	{
    		Fapi_doMarginReadByByte((uint8_t *)src,
    								(uint8_t *)dst,
    								(uint32_t) bytes,                //16
    								Fapi_NormalRead);
    		src += bytes;
    		dst += bytes;
            bytes_remain -= bytes;
        }
    	return (0);
    }