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.

TMS570LC4357: Flash write can be only executed once

Part Number: TMS570LC4357


Hi,

I am trying to write Flash in program. I am referring to CAN bootloader example. I can find the data is programmed into last sector of Bank 1. However, I found this sector can be only programmed once. I cannot program new into this sector. Here is my code for reference. Could someone please provide some guidance about this issue? Thanks.

/* Initialize the flash bank and activate the sectors */
uint32_t Fapi_Init(uint32_t ucStartBank, uint32_t ucEndBank)
{
    uint32_t i;

    /*SYS_CLK_FREQ is defined in bl_config.h */
    if ((Fapi_initializeFlashBanks((uint32_t)SYS_CLK_FREQ)) == Fapi_Status_Success)
    {
        for (i = ucStartBank; i < ( ucEndBank + 1); i++)
        {
            (void)Fapi_setActiveFlashBank((Fapi_FlashBankType)i);
            (void)Fapi_enableMainBankSectors(0xFFFF);                    /* used for API 2.01*/
            while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
            while( FAPI_GET_FSM_STATUS != Fapi_Status_Success ); /* don't have to include this one*/
        }
        g_ulBankInitialized = 1;

    }
    else
    {
         return (1);
    }
    return (0); //success
}

/* ulAddr must be starting address of one flash sector*/
uint32_t Fapi_BlockErase(uint32_t ulAddr, uint32_t Size)
{
    uint8_t  i=0, ucStartSector, ucEndSector;
    uint32_t EndAddr, status;

    EndAddr = ulAddr + Size;
    for (i = 0; i < NUMBEROFSECTORS; i++)
    {
        if (ulAddr <= (uint32_t)(flash_sector[i].start))
        {
            g_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))
        {
            g_ucEndBank   = flash_sector[i].bankNumber;
            ucEndSector = i;
            break;
        }
    }

    status = Fapi_Init(g_ucStartBank, g_ucEndBank);
    if (status == 0)        // initialization succeeds
    {
        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);
        }
    }

    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 Flash_Address, uint32_t Data_Address, uint32_t SizeInBytes)
{
    register uint32_t src = Data_Address;
    register uint32_t dst = Flash_Address;
    uint32_t bytes;

    if (SizeInBytes < 16u)
        bytes = SizeInBytes;
    else
        bytes = 16;

    /* The flash bank has been initialized in flash erase function */
    if (g_ulBankInitialized |= 1 )
    {
        Fapi_Init(g_ucStartBank, g_ucEndBank);
    }

    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 );
        while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);

        Fapi_flushPipeline();

        src += bytes;
        dst += bytes;
        SizeInBytes -= bytes;
        if ( SizeInBytes < 32){
           bytes = SizeInBytes;
        }
    }
    return (0);
}

void Flash_Write_Test(void)
{
    static uint8 seqFlashWrite = 1;
    uint32 dbIdx = 0;
    uint32 dbCnt = FLASH_TEST_SECTOR_SIZE / FLASH_WRITE_BLOCK_SIZE;
    uint32 retCode = Fapi_BlockErase(FLASH_TEST_SECTOR_BASE_ADDRESS, FLASH_TEST_SECTOR_SIZE);
    uint8  checksum[CHECKSUM_REDUNDANT_SIZE] = {0};
    uint8  u8PotStringBuf[128];

    uint8 dataBlock[FLASH_WRITE_BLOCK_SIZE];
    uint8 seed = (seqFlashWrite) % FLASH_WRITE_BLOCK_SIZE;
    uint8 i = 0;

    // Return an error if an access violation occurred.
    if(retCode)
    {
        sprintf(u8PotStringBuf,"[Failed]-[Seq#%d]-Flash Write Test: 16KB Erase \r\n", seqFlashWrite);
        sciDisplayText(UART_Msg, u8PotStringBuf);
#ifdef  DEBUG_ON
        sciDisplayText(UART_Debug, u8PotStringBuf);
#endif
        seqFlashWrite++;
        return;
    }
    else
    {
        sprintf(u8PotStringBuf,"[Passed]-[Seq#%d]-Flash Write Test: 16KB Erase \r\n", seqFlashWrite);
        sciDisplayText(UART_Msg, u8PotStringBuf);
#ifdef  DEBUG_ON
        sciDisplayText(UART_Debug, u8PotStringBuf);
#endif
    }

    retCode = 0;

    // generate data for Flash writing
    for(i = 0; i < FLASH_WRITE_BLOCK_SIZE; i++)
        dataBlock[i] = seed++;
    for(i = 0; i < CHECKSUM_REDUNDANT_SIZE; i++)
        checksum[i] = checksum8_2_compliment(dataBlock, FLASH_WRITE_BLOCK_SIZE);

    for(dbIdx = 0; dbIdx < dbCnt; dbIdx++)
    {
        // set seed equals to data block index + execution sequence number
        uint32 address = FLASH_TEST_SECTOR_BASE_ADDRESS + dbIdx * FLASH_WRITE_BLOCK_SIZE;
        // program Flash with data block
        retCode = Fapi_BlockProgram(address, (uint32_t)&dataBlock[0], FLASH_WRITE_BLOCK_SIZE);

        if(retCode)
        {
            break;
        }
    }


    if(retCode)
    {
        sprintf(u8PotStringBuf,"[Failed]-[Seq#%d]-Flash Write Test: 16KB Program \r\n", seqFlashWrite);
        sciDisplayText(UART_Msg, u8PotStringBuf);
#ifdef  DEBUG_ON
        sciDisplayText(UART_Debug, u8PotStringBuf);
#endif
    }
    else
    {
        uint8 i = 0;
        sprintf(u8PotStringBuf,"[Passed]-[Seq#%d]-Flash Write Test: 16KB Program. Checksum is:[ ", seqFlashWrite);
        sciDisplayText(UART_Msg, u8PotStringBuf);
#ifdef  DEBUG_ON
        sciDisplayText(UART_Debug, u8PotStringBuf);
#endif
        // store checksum into redundant data array
        for(i=0; i<CHECKSUM_REDUNDANT_SIZE; i++)
        {
            Flash_Checksum[i] = checksum[i];

            sprintf(u8PotStringBuf, "0x%0x ", checksum[i]);
            sciDisplayText(UART_Msg, u8PotStringBuf);
#ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, u8PotStringBuf);
#endif
        }

        sciDisplayText(UART_Msg, "]\r\n");
#ifdef  DEBUG_ON
        sciDisplayText(UART_Debug, "]\r\n");
#endif

    }
    seqFlashWrite++;
}

// main.c

// initialize Flash data for reading
    Flash_Write_Test();
    // initialize RAM data for reading
    RAM_Write_Test();
    Flash_Read_Test();

    Flash_Write_Test();
    Flash_Read_Test();

    Flash_Write_Test();
    Flash_Read_Test();

    while(1)
    {

    }

  • Hi Bob,

    After the flash sector is erased, the content of the flash sector becomes 0xFFFFFFFF. The flash program operation can only flip the flash bit cell from 1 to 0. So before writing data to the flash sector, you need to erase the sector to ensure the content of the sector is 0xFFFFFFFF.

  • Hi, QJ,

    Glad to have the reply from the author who wrote the code I am referring to now.

    Yes, I did the erasing operation as below.  Actually, all Flash operation code are from CAN bootloader for TMS570LC4357. The trick thing is: I can see Flash programming successful for the first time, but fail in the following sequencing.

    Could you please help on two questions?

    1. shall I change the TMS570LC4357 into supervisor mode? If so, how?

    2. Must I copy the flash code into RAM instead of Flash? If so, how should I change the link file? I tried, but got the error like this

    #10099-D program will not fit into available memory, or the section contains a call site that requires a trampoline that can't be generated for this section. run placement with alignment fails for section "flashAPI" size 0xd74

    ...................................................................................................

    Erase & program operation

    --------------------------------------------------------------------------

    void Flash_Write_Test(void)
    {
        static uint8 seqFlashWrite = 1;
        uint32 dbIdx = 0;
        uint32 dbCnt = FLASH_TEST_SECTOR_SIZE / FLASH_WRITE_BLOCK_SIZE;
        uint32 retCode = Fapi_BlockErase(FLASH_TEST_SECTOR_BASE_ADDRESS, FLASH_TEST_SECTOR_SIZE);
        uint8  checksum[CHECKSUM_REDUNDANT_SIZE] = {0};
        uint8  u8PotStringBuf[128];

        uint8 dataBlock[FLASH_WRITE_BLOCK_SIZE];
        uint8 seed = (seqFlashWrite) % FLASH_WRITE_BLOCK_SIZE;
        uint8 i = 0;

        // Return an error if an access violation occurred.
        if(retCode)
        {
            sprintf(u8PotStringBuf,"[Failed]-[Seq#%d]-Flash Write Test: 16KB Erase \r\n", seqFlashWrite);
            sciDisplayText(UART_Msg, u8PotStringBuf);
    #ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, u8PotStringBuf);
    #endif
            seqFlashWrite++;
            return;
        }
        else
        {
            sprintf(u8PotStringBuf,"[Passed]-[Seq#%d]-Flash Write Test: 16KB Erase \r\n", seqFlashWrite);
            sciDisplayText(UART_Msg, u8PotStringBuf);
    #ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, u8PotStringBuf);
    #endif
        }

        retCode = 0;

        // generate data for Flash writing
        for(i = 0; i < FLASH_WRITE_BLOCK_SIZE; i++)
            dataBlock[i] = seed++;
        for(i = 0; i < CHECKSUM_REDUNDANT_SIZE; i++)
            checksum[i] = checksum8_2_compliment(dataBlock, FLASH_WRITE_BLOCK_SIZE);

        for(dbIdx = 0; dbIdx < dbCnt; dbIdx++)
        {
            // set seed equals to data block index + execution sequence number
            uint32 address = FLASH_TEST_SECTOR_BASE_ADDRESS + dbIdx * FLASH_WRITE_BLOCK_SIZE;
            // program Flash with data block
            retCode = Fapi_BlockProgram(address, (uint32_t)&dataBlock[0], FLASH_WRITE_BLOCK_SIZE);

            if(retCode)
            {
                break;
            }
        }


        if(retCode)
        {
            sprintf(u8PotStringBuf,"[Failed]-[Seq#%d]-Flash Write Test: 16KB Program \r\n", seqFlashWrite);
            sciDisplayText(UART_Msg, u8PotStringBuf);
    #ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, u8PotStringBuf);
    #endif
        }
        else
        {
            uint8 i = 0;
            sprintf(u8PotStringBuf,"[Passed]-[Seq#%d]-Flash Write Test: 16KB Program. Checksum is:[ ", seqFlashWrite);
            sciDisplayText(UART_Msg, u8PotStringBuf);
    #ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, u8PotStringBuf);
    #endif
            // store checksum into redundant data array
            for(i=0; i<CHECKSUM_REDUNDANT_SIZE; i++)
            {
                Flash_Checksum[i] = checksum[i];

                sprintf(u8PotStringBuf, "0x%0x ", checksum[i]);
                sciDisplayText(UART_Msg, u8PotStringBuf);
    #ifdef  DEBUG_ON
                sciDisplayText(UART_Debug, u8PotStringBuf);
    #endif
            }

            sciDisplayText(UART_Msg, "]\r\n");
    #ifdef  DEBUG_ON
            sciDisplayText(UART_Debug, "]\r\n");
    #endif

        }
        seqFlashWrite++;
    }

  • one more comment: in the second and following writing operation, I can see erasing fails as the Flash reading by XDS110 debug view is not changed to 0xFFFFFFF

  • Hi, QJ,

    I have solved the link command file problem. Now, I can copy Flash operation code into RAM which can be verified by Memory view of CCS debug windows (see figure below). However, I meet another problem. When the code run to Fapi_BlockErase, it crashes and enter to code as below. So any suggestion on this issue? Thanks in advanced.

    prefetchEntry
            b   prefetchEntry

  • 1. shall I change the TMS570LC4357 into supervisor mode? If so, how?

    2. Must I copy the flash code into RAM instead of Flash? If so, how should I change the link file? I tried, but got the error like this

    1. Yes, the F021 flash APIs should be executed in supervisor mode. The device is in supervisor mode (not user mode) by default.

    2. No really. The TMS570LC43x has two flash banks. You can run your code from Bank0, and program the data to flash Bank1. If your code is located in Bank 0, and want to program data to locations in Bank 0 too, you need to copy the Flash API related code to SRAM, and run the code from the SRAM.

  • When the code run to Fapi_BlockErase, it crashes and enter to code as below. So any suggestion on this issue?

    Are Fapi_BlockEase() and Fapi_BlockProgram() copied to SRAM?

  • Yes, Copied to SRAM. I am guessing this is caused by Trampoline functions,feature provided by linker to treat far call as near call. All Erase, Program, Read functions are treated as Trampoline functions as below in map file. Do you meet this issue during debug copying code from Flash to RAM? Thanks in advanced.

    FAR CALL TRAMPOLINES

    callee name               trampoline name
       callee addr  tramp addr   call addr  call info
    --------------  -----------  ---------  ----------------
    Fapi_BlockRead            $Tramp$AA$L$PI$$Fapi_BlockRead
       0800209c     0000a5ec     00002590   memory_test.obj (.text)
    Fapi_BlockProgram         $Tramp$AA$L$PI$$Fapi_BlockProgram
       08001f80     0000a5f4     00002378   memory_test.obj (.text)
    Fapi_BlockErase           $Tramp$AA$L$PI$$Fapi_BlockErase
       08001da8     0000a5fc     0000220c   memory_test.obj (.text)

    [3 trampolines]
    [3 trampoline calls]

  • Hi Bob,

    The trampoline functions will not generate prefetch abort. 

    The Prefetch Abort can be analyzed by reading the Instruction Fault Status Register (IFSR), the Instruction Fault Address Register (IFAR). IFAR contains the address where the CPU was trying to fetch an instruction from. The contents of IFAR is always valid for a Prefetch Abort, because all Prefetch Aborts are synchronous.

  • Hi, QJ,

    Thanks for replying. After more debug, I found programming failure may be caused by erasing failure. I found the following phenomenon:

    When system is power-on reset, the sector I chosen (sector#15 in Bank#1) is erased to all "0xFF". Then the first programming successes. However, in the next round of programming operation, a erasing operation prior to "sector programming" does not take a effect - still same data as last programmed (I check this result through memory view in debug mode).  As you mentioned early, the Flash can be only changed from 0xFF to desired value (can only flip the flash bit cell from 1 to 0). I think this is the root cause.

    I checked all documents related with Flash programming, such as SNPA241, SPNU501G, SPNA148, SPNU563a, SPNS195C (datasheet), however, I have no idea about how erase operation fails. I even try to step into debug for binary code of F021 API, but nothing is found. Could you please help me on this issue? Is there any mistake usage or setting to cause this?

    Here is more project setting for your reference.

    1. I am trying to periodical program sector#15 of Bank#1 during main program running (every 2880 second)

    2. I do not copy Flash operation code into RAM

    3. All .text code are simple enough to map into Bank#0

    4. No special processing for ECC. Just use project default setting

    Thanks a lot in advanced.

    Regards,

    Bob

  • Hi Bob,

    You can erase the flash sectors repeatedly without any issue. I did it like this:

    uint32_t Success[] = {0xea0004bd, 0x00000000,
    0x00000000, 0x00000000,
    0x00000000, 0x00000000,
    0x00000000, 0x00000000,
    0x4605b538, 0x2d06460c,
    0x2d08d005, 0x2d0ed003,
    0x2005bf18, 0x2010d108,
    0xfa34f000, 0x60044803};

    status = Fapi_BlockErase(0x03E0000, 0x1000);
    status = Fapi_BlockProgram(0x03E0000, (unsigned int)&Success, 64);
    status = Fapi_BlockErase(0x03E0000, 0x1000);
    status = Fapi_BlockProgram(0x03E0000, (unsigned int)&Success, 64);

  • Hi, QJ,

    Thanks for timely reply. Could you please share this example project to me? 

    Regards,

    Bob

  • Hi Bob,

    I am using the same flash code: bl_flash.c

  • There is one bug in bl_flash.c when the flash address (ulAddr) in Fapi_BlockErase(uint32_t ulAddr, uint32_t Size) call is equal to the start address of the last flash sector (for example 0x3e0000 for tms570lc43x). 

    The updated the code is:

    /*****************************************************************************
     *
     * bl_flash.c     : The file holds the main control loop of the boot loader.
     * Author         : QJ Wang. qjwang@ti.com
     * Date           : 4-19-2019
     */
    /* Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    //*****************************************************************************
    
    #include "bl_config.h"
    #include "bl_flash.h"
    #include "F021.h"
    #include "flash_defines.h"
    
    
    //#define Freq_In_MHz = SYS_CLK_FREQ;
    uint8_t    g_ucStartBank, g_ucEndBank, g_ucStartSector, g_ucEndSector;
    uint32_t   g_ulBankInitialized = 0;
    
    //*****************************************************************************
    //
    // 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;
    
    	/* The start address must be at the beginning 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);
        }
    }
    
    /* Initialize the flash bank and activate the sectors */
    uint32_t Fapi_Init(uint32_t ucStartBank, uint32_t ucEndBank)
    {
        uint32_t i;
    
        /*SYS_CLK_FREQ is defined in bl_config.h */
        if ((Fapi_initializeFlashBanks((uint32_t)SYS_CLK_FREQ)) == Fapi_Status_Success){
            for (i = ucStartBank; i < ( ucEndBank + 1); i++){
                (void)Fapi_setActiveFlashBank((Fapi_FlashBankType)i);
                (void)Fapi_enableMainBankSectors(0xFFFF);                    /* used for API 2.01*/
                while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
                while( FAPI_GET_FSM_STATUS != Fapi_Status_Success ); /* don't have to include this one*/
            }
            g_ulBankInitialized = 1;
    
        }else {
             return (1);
        }
        return (0); //success
    }
    
    /* ulAddr must be starting address of one flash sector*/
    uint32_t Fapi_BlockErase(uint32_t ulAddr, uint32_t Size)
    {
    	uint8_t  i=0, ucStartSector, ucEndSector;
        uint32_t EndAddr, status;
    
    	EndAddr = ulAddr + Size;
    	for (i = 0; i < NUMBEROFSECTORS; i++){
    		if (ulAddr < (uint32_t)(flash_sector[i].start))
    		{
    			g_ucStartBank     = flash_sector[i-1].bankNumber;
    		    ucStartSector   = i-1;
    		    break;
    		}
    		else if (ulAddr == (uint32_t)(flash_sector[i].start))
    		{
                g_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))
    		{
    			g_ucEndBank   = flash_sector[i].bankNumber;
    			ucEndSector = i;
    		    break;
    		}
    	}
    
        status = Fapi_Init(g_ucStartBank, g_ucEndBank);
    
        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);
        }
    
    #if defined (RM57) || defined (TMS570LC43)
        status =  0;
    #else
        status =  Flash_Erase_Check((uint32_t)ulAddr, Size);
    #endif
    
    	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 Flash_Address, uint32_t Data_Address, uint32_t SizeInBytes)
    {
    	register uint32_t src = Data_Address;
    	register uint32_t dst = Flash_Address;
    	uint32_t bytes;
    
    	if (SizeInBytes < 16)
    		bytes = SizeInBytes;
    	else
    		bytes = 16;
    
        /* The flash bank has been initialized in flash erase function */
        if (g_ulBankInitialized |= 1 ){
            Fapi_Init(g_ucStartBank, g_ucEndBank);
        }
    
        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 );
            while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
    
    		src += bytes;
    		dst += bytes;
    		SizeInBytes -= bytes;
            if ( SizeInBytes < 32){
               bytes = SizeInBytes;
            }
        }
    	return (0);
    }
    
    
    uint32_t Fapi_UpdateStatusProgram(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;
    
    	if (Size_In_Bytes < 16)
    		bytes = Size_In_Bytes;
    	else
    		bytes = 16;
    
    	Fapi_issueProgrammingCommand((uint32_t *)dst,
    									 (uint8_t *)src,
    									 (uint32_t) bytes,
    									 0,
    									 0,
    									 Fapi_AutoEccGeneration);
    
     	while( Fapi_checkFsmForReady() == Fapi_Status_FsmBusy );
        while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
    
    	return (0);
    }
    
    
    
    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 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);
    }