TMS570LS0914: code crash at Fapi_setActiveFlashBank() while write and erase on the main banks

Part Number: TMS570LS0914

Hello,

I am trying to write some data to flash. but the code gets crash at Fapi_setActiveFlashBank(bank0).

this happens specifiaclly bank0. before calling this function I have copied code from falsh to ram.

for writing to flash can I use flash bank1 or I have to start write from flash bank0 only?

the squence of write is :

  1. Check whether the address range falls within the Flash Memory
  2. Iterate through the banks in the Flash
  3. Check whether the address falls within the bank
  4. Set the bank to an active state
  5. Retrieve the list of sectors to be enabled
  6. Enable the sectors to be written
  7. Wait for the operation to complete
  8. Iterate through the addresses in the Flash Bank
  9. Set the number of bytes to be written in the next operation
  10. Write to the Flash address
  11. Wait for the operation to complete
  12. Check whether the operation is successful
  13. Update the buffer pointer, flash address and the number of bytes left for the next operation
  14. Control goes to step 8 and keep iterating till valid address
  15. After completing the iteration, If an error is encountered or the write operation is complete, exit the loop of step 2.

my writting address is 0x000E0000 and data to write is 0xAA.

kindly help me to resolve this issue.

  • Hi Prajakta,

    Your UNDEF interrupt crash at Fapi_setActiveFlashBank() is a well-documented issue on the TMS570LS0914. The root cause is that the F021 Flash API is still executing from flash memory when it tries to modify that same flash bank [1][2].

    The TMS570LS0914 is a single-bank device — all flash (0x00000000 to 0x000FFFFF) resides in Bank 0. This means:

    "The F021 Flash API library cannot be executed from the same bank as the active bank selected for the API commands to operate on. On single bank devices, the F021 Flash API must be executed from RAM." [1]

    You mention copying code from flash to RAM, but the crash indicates that not all F021 API functions are actually executing from RAM. Simply copying your application code isn't enough — the entire F021 library and all related object files must be linked to run from RAM.

    The Fix

    1. Modify your linker command file to place all F021 API code with separate load (Flash) and run (RAM) addresses [3]:

    flashAPI:
    {
        Fapi_UserDefinedFunctions.obj (.text, .data)
        bl_flash.obj (.text, .data)
        --library= F021_API_CortexR4_BE_V3D16.lib (.text, .data)
    } palign=8 load = FLASH0, run = SRAM, LOAD_START(apiLoadStart), RUN_START(apiRunStart), SIZE(apiLoadSize)

    2. Copy the API to RAM before calling any flash functions [1]:

    extern unsigned int apiLoadStart;
    extern unsigned int apiRunStart;
    extern unsigned int apiLoadSize;
    
    memcpy(&apiRunStart, &apiLoadStart, (uint32)&apiLoadSize);

    3. Critical detail: Include both .text and .data sections for all related object files (including bl_flash.obj). Missing .text in any of these objects will cause the code to remain in flash and trigger the UNDEF exception [4].


    Additional Requirements

    • Privilege mode: The F021 APIs must run in supervisor/privilege mode (not user mode) to access Flash Memory Controller registers [5].
    • HCLK frequency: Ensure Fapi_initializeFlashBanks() receives the correct HCLK value — 160 MHz for TMS570LS0914PGE [5].
    • Disable interrupts during flash operations [5].
    • Flash wait states (RWAIT): Must be configured properly for your operating frequency before flash operations [6].

    Regarding Your Bank Question

    Your write address 0x000E0000 falls in sector 13 of Bank 0, which is valid [7]. Since the TMS570LS0914 is a single-bank device, you must use Bank 0 — there is no separate Bank 1 available for data storage. You don't need to "start from bank0" in any particular order; you just need the API running from RAM so it can safely operate on Bank 0.


    To help refine this recommendation, it would be helpful to know:

    • Your current linker command file configuration (to verify all F021 objects are in the RAM-execution section)
    • The HCLK frequency you're passing to Fapi_initializeFlashBanks()
    • Whether your application is running in supervisor mode or user mode when the crash occurs
    • Whether you're using the Big Endian (_BE) or Little Endian variant of the F021 library matching your build configuration

    1. TMS570LS0914: F021 API on TMS570LS0914PGE - TI E2E
    2. F021 Flash API Reference - SPNU501
    3. TMS570LS0914 CAN Bootloader Issue - TI E2E
    4. TMS570LS0914 CAN Bootloader - Missing .text fix
    5. Hercules Bootloader Application Note - SPNA241
    6. TMS570LS0x Technical Reference Manual - SPNU607A
    7. TMS570LS0914: Uniflash Flash Memory Map

    Best Regards,

    Zackary Fleenor

  • Hi Zackary Fleenor,

    Thank you for your response.

    I have gone through the explanation given by you. still I am in confusion about the linker cmd file. I am attaching the linker cmd file and flash interface file with this. Kindly have a glance to both of them and give me the suggestion what should I change.

    Thanks,

    Prajakta

  •     

    /*----------------------------------------------------------------------------*/
    /* sys_link.cmd                                                               */
    /*                                                                            */
    /* 
    * Copyright (C) 2009-2016 Texas Instruments Incorporated - 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.
    *
    */
    
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* USER CODE BEGIN (0) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Linker Settings                                                            */
    
    --retain="*(.intvecs)"
    
    /* USER CODE BEGIN (1) */
    /* USER CODE END */
    
    /*----------------------------------------------------------------------------*/
    /* Memory Map                                                                 */
    
    MEMORY
    {
     	VECTORS (X)  : origin=0x00020000 length=0x00000020 vfill = 0xffffffff
        FLASH0  (RX) : origin=0x00020020 length=0x000FFFE0 vfill = 0xffffffff
       STACKS  (RW) : origin=0x08000000 length=0x00001500
        RAM     (RW) : origin=0x08001500 length=0x0001EB00
    
    /* USER CODE BEGIN (2) */
    #if 1
    	/* Add memory regions corresponding to the ECC area of the flash bank */
    	ECC_VEC (R) : origin=(0xf0400000 + (start(VECTORS) >> 3))
    	length=(size(VECTORS) >> 3)
    	ECC={algorithm=algoL2R5F021, input_range=VECTORS}
    	ECC_FLA0 (R) : origin=(0xf0400000 + (start(FLASH0) >> 3))
    	length=(size(FLASH0) >> 3)
    	ECC={algorithm=algoL2R5F021, input_range=FLASH0 }
    #endif
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (3) */
    /* Add an ECC {} directive describing the algorithm that matches the device */
    ECC
    {
    	algoL2R5F021 : address_mask = 0xfffffff8 /*Address Bits 31:3 */
    	hamming_mask = R4 /*Use R4/R5 build in Mask */
    	parity_mask = 0x0c /*Set which ECC bits are Even & Odd parity */
    	mirroring = F021 /*RM57Lx and TMS570LCx are build in F021*/
    }
    /* USER CODE END */
    
    /*----------------------------------------------------------------------------*/
    /* Section Configuration                                                      */
    
    SECTIONS
    {
        .intvecs : {} > VECTORS
        .TI.ramfunc align(32) : {	-l F021_API_CortexR4_BE_V3D16.lib(.text) }
    								LOAD=FLASH0, RUN=RAM,
    								LOAD_START(RamfuncsLoadStart),
    								RUN_START(RamfuncsRunStart),
    								SIZE(RamfuncsLoadSize)
    
        .text    : {} > FLASH0 
        .const   : {} > FLASH0 
        .cinit   : {} > FLASH0 
        .pinit   : {} > FLASH0 
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
        
        FEE_TEXT_SECTION : {} > FLASH0 
        FEE_CONST_SECTION : {} > FLASH0
        FEE_DATA_SECTION : {} > RAM
    
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (5) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Misc                                                                       */
    
    /* USER CODE BEGIN (6) */
    /* USER CODE END */
    /*----------------------------------------------------------------------------*/
    

  • /*******************************************************************************
    ** Copyright (c) 2022 KPTL
    **
    ** This software is the property of KPTL.
    ** It can not be used, duplicated and/or distributed without the express
    ** permission of KPTL.
    **
    ** -----------------------------------------------------------------------------
    ** File Name    : FlashIntf.c
    ** Module Name  : Flash Module BSW Source File
    ** -----------------------------------------------------------------------------
    **
    ** Description : To implement routines that provide applications with a
    **               simplified interface to the underlying (low-level)
    **               Flash (F021) driver
    **
    ** This file must exclusively contain information needed to
    ** use this component.
    **
    ********************************************************************************
    ** R E V I S I O N  H I S T O R Y
    ********************************************************************************
    ** V01.00 24/12/2021    Initial Creation
    ********************************************************************************/
    #include "system.h"
    #include "sys_core.h"
    
    #include "F021.h"
    
    #include "FlashIntf.h"
    #include "FlashIntf_Cfg.h"
    
    
    /* Data structure to hold Device Flash Information */
    static FlashDevInfo_t St_FDevInfo = {0};
    
    
    /* Prototypes for static functions */
    static uint64_t FlashIntf_GetWriteSectorMask(Fapi_FlashBankType Enm_Bank, uint32_t Ui_StartAddr, uint32_t Ui_EndAddr);
    static FlashIntf_RetCode_t FlashIntf_MainBankWrite(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen);
    static FlashIntf_RetCode_t FlashIntf_EEBankWrite(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen);
    static uint64_t FlashIntf_GetEraseSectorMask(Fapi_FlashBankType Enm_Bank, uint32_t Ui_StartAddr, uint16_t *Ptr_UsNSectorsLeft, Fapi_FlashSectorType *Ptr_EnmFirstSector);
    static FlashIntf_RetCode_t FlashIntf_EraseMainBankSectors(uint32_t Ui_StartAddr, uint16_t Us_NSectors);
    static FlashIntf_RetCode_t FlashIntf_EraseEEBankSectors(uint32_t Ui_StartAddr, uint16_t Us_NSectors);
    static FlashIntf_RetCode_t FlashIntf_EraseMainBanks(uint32_t Ui_StartAddr, uint16_t Us_NBanks);
    static FlashIntf_RetCode_t FlashIntf_EraseEEBank(uint32_t Ui_Addr);
    static FlashIntf_RetCode_t FlashIntf_MainBankRead(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen);
    static FlashIntf_RetCode_t FlashIntf_EEBankRead(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen);
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_Init, ".TI.ramfunc");
    #endif
    /* Function to initialize the Flash Interface */
    FlashIntf_RetCode_t FlashIntf_Init(void)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_NULLPTR;
    	Fapi_FlashBankSectorsType St_BankInfo;
    	Fapi_DeviceInfoType St_DevInfo;
    	Fapi_FlashBankType Enm_BankIter;
    	Fapi_FlashSectorType Enm_SecIter;
    	uint32_t Ui_Addr;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Initialize the Flash Memory Banks before performing any operation */
    	Enm_Ret = (FlashIntf_RetCode_t)Fapi_initializeFlashBanks((uint32_t)HCLK_FREQ);
    	if (Enm_Ret == FLASHINTF_SUCCESS)
    	{
    		/* Retrieve device information */
    		St_DevInfo = Fapi_getDeviceInfo();
    		if (St_DevInfo.u16NumberOfBanks <= FLASH_MAXBANKS)
    		{
    			/* Set the number of banks into the Flash Information Structure */
    			St_FDevInfo.Us_NBanks = St_DevInfo.u16NumberOfBanks;
    			/* Iterate through the Flash Banks */
    			for (Enm_BankIter = Fapi_FlashBank0; Enm_BankIter < FLASH_MAXBANKS; Enm_BankIter++)
    			{
    				/* Retrieve and store bank information in the Flash Information Structure */
    				Enm_Ret = (FlashIntf_RetCode_t)Fapi_getBankSectors(Enm_BankIter, &St_BankInfo);
    				if (Enm_Ret == FLASHINTF_SUCCESS)
    				{
    					St_FDevInfo.St_ArrBankInfo[Enm_BankIter].Ui_NSectors = St_BankInfo.u32NumberOfSectors;
    					Ui_Addr = St_BankInfo.u32BankStartAddress;
    					St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_StartAddr = Ui_Addr;
    
    					/* Iterate through the sectors in the bank */
    					for (Enm_SecIter = Fapi_FlashSector0; Enm_SecIter < St_BankInfo.u32NumberOfSectors; Enm_SecIter++)
    					{
    						/* Store sector information in the Flash Information Structure */
    						St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_ArrSecAddr[Enm_SecIter].Ui_StartAddr = Ui_Addr;
    						if (St_BankInfo.oFlashBankTech == Fapi_FLEE)
    						{
    							Ui_Addr += (uint32_t)St_BankInfo.au16SectorSizes[Fapi_FlashSector0] * 1024U;
    						}
    						else
    						{
    							Ui_Addr += (uint32_t)St_BankInfo.au16SectorSizes[Enm_SecIter] * 1024U;
    						}
    
    						St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr = (Ui_Addr - 1U);
    					}
    
    					St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr = (Ui_Addr - 1U);
    				}
    			}
    
    			/* Store the Flash addresses in the Flash Information Structure*/
    			St_FDevInfo.St_FlashAddr.Ui_StartAddr = St_FDevInfo.St_ArrBankInfo[Fapi_FlashBank0].St_ArrSecAddr[Fapi_FlashSector0].Ui_StartAddr;
    			St_FDevInfo.St_FlashAddr.Ui_EndAddr = (St_FDevInfo.St_FlashAddr.Ui_StartAddr + ((uint32_t)St_DevInfo.u16DeviceMemorySize * 1024U) - 1U);
    		}
    		else
    		{
    			Enm_Ret = FLASHINTF_FAIL;
    		}
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_GetWriteSectorMask, ".TI.ramfunc");
    #endif
    /* Function to retrieve the sectors to be enabled for a Flash/FEE write operation */
    static uint64_t FlashIntf_GetWriteSectorMask(Fapi_FlashBankType Enm_Bank, uint32_t Ui_StartAddr, uint32_t Ui_EndAddr)
    {
    	uint64_t Ul_SectorMask = 0U;
    	Fapi_FlashSectorType Enm_SecIter;
    
    	/* Iterate through the sectors in the Flash */
    	for (Enm_SecIter = Fapi_FlashSector0; Enm_SecIter < St_FDevInfo.St_ArrBankInfo[Enm_Bank].Ui_NSectors; Enm_SecIter++)
    	{
    		/* Determine the first sector for the write */
    		if (Ul_SectorMask == 0U)
    		{
    			/* If the address falls within the sector, set the sector bit in the mask */
    			if ((Ui_StartAddr >= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_StartAddr)
    					&& (Ui_StartAddr <= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr))
    			{
    				Ul_SectorMask |= (uint64_t)((uint64_t)1U << Enm_SecIter);
    			}
    		}
    		else
    		{
    			/* Set subsequent bits in the mask till the end address is reached */
    			Ul_SectorMask |= (uint64_t)((uint64_t)1U << Enm_SecIter);
    		}
    
    		/* If the end address falls within the sector, exit the loop */
    		if ((Ui_EndAddr >= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_StartAddr)
    				&& (Ui_EndAddr <= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr))
    		{
    			break;
    		}
    	}
    
    	return Ul_SectorMask;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_MainBankWrite, ".TI.ramfunc");
    #endif
    /* Function to write data to the Main Flash Memory */
    static FlashIntf_RetCode_t FlashIntf_MainBankWrite(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_SUCCESS;
    	Fapi_FlashBankType Enm_BankIter;
    	uint16_t Us_SectorMask = 0U;
    	uint32_t Ui_EndAddr = (Ui_StartAddr + Us_BufLen - 1U);
    	uint32_t Ui_Addr = Ui_StartAddr;
    	uint16_t Us_NWBytes;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Check whether the address range falls within the Flash Memory */
    	if ((Ui_StartAddr >= St_FDevInfo.St_FlashAddr.Ui_StartAddr) && (Ui_EndAddr <= St_FDevInfo.St_FlashAddr.Ui_EndAddr))
    	{
    		/* Iterate through the banks in the Flash */
    		for (Enm_BankIter = Fapi_FlashBank0; Enm_BankIter < St_FDevInfo.Us_NBanks; Enm_BankIter++)
    		{
    			/* Check whether the address falls within the bank */
    			if ((Ui_Addr >= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_StartAddr)
    					&& (Ui_Addr <= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr))
    			{
    				/* Set the bank to an active state */
    				Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(Enm_BankIter);
    				if (Enm_Ret == FLASHINTF_SUCCESS)
    				{
    					/* Retrieve the list of sectors to be enabled */
    					Us_SectorMask = (uint16_t)FlashIntf_GetWriteSectorMask(Enm_BankIter, Ui_Addr, Ui_EndAddr);
    					if (Us_SectorMask != 0U)
    					{
    						/* Enable the sectors to be written */
    						Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableMainBankSectors(Us_SectorMask);
    						if (Enm_Ret == FLASHINTF_SUCCESS)
    						{
    							/* Wait for the operation to complete */
    							while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    							{
    							}
    
    							/* Iterate through the addresses in the Flash Bank */
    							while ((Ui_Addr < St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr) && (Ui_Addr <= Ui_EndAddr))
    							{
    								/* Set the number of bytes to be written in the next operation */
    								Us_NWBytes = (FLASH_MAINBANKWIDTH - (uint16_t)(Ui_Addr % FLASH_MAINBANKWIDTH));
    								if (Us_NWBytes > Us_BufLen)
    								{
    									Us_NWBytes = Us_BufLen;
    								}
    
    								/* Write to the Flash address */
    								Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueProgrammingCommand((uint32_t *)Ui_Addr, Ptr_UcBuf, (uint8_t)Us_NWBytes, NULL, 0U, Fapi_AutoEccGeneration);
    								if (Enm_Ret != FLASHINTF_SUCCESS)
    								{
    									break;
    								}
    
    								/* Wait for the operation to complete */
    								while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    								{
    								}
    
    								/* Check whether the operation is successful */
    								if (FAPI_GET_FSM_STATUS != 0U)
    								{
    									Enm_Ret = FLASHINTF_FAIL;
    									break;
    								}
    
    								/* Update the buffer pointer, flash address and the number of bytes left for the next operation */
    								Ptr_UcBuf += Us_NWBytes;
    								Ui_Addr += Us_NWBytes;
    								Us_BufLen -= Us_NWBytes;
    							}
    						}
    					}
    				}
    			}
    
    			/* If an error is encountered or the write operation is complete, exit the loop */
    			if ((Enm_Ret != FLASHINTF_SUCCESS) || (Us_BufLen == 0U))
    			{
    				break;
    			}
    		}
    	}
    	else
    	{
    	    Enm_Ret = FLASHINTF_INVADDR;
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EEBankWrite, ".TI.ramfunc");
    #endif
    /* Function to write data to the Flash EEPROM Memory */
    static FlashIntf_RetCode_t FlashIntf_EEBankWrite(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_INVADDR;
    	uint64_t Ul_SectorMask = 0U;
    	uint32_t Ui_EndAddr = (Ui_StartAddr + Us_BufLen - 1U);
    	uint32_t Ui_Addr = Ui_StartAddr;
    	uint16_t Us_NWBytes;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Check whether the address range falls within the FEE Bank */
    	if ((Ui_StartAddr >= St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_BankAddr.Ui_StartAddr) && (Ui_EndAddr <= St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_BankAddr.Ui_EndAddr))
    	{
    		/* Set the bank to an active state */
    		Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(FLASH_EEBANK);
    		if (Enm_Ret == FLASHINTF_SUCCESS)
    		{
    			/* Retrieve the list of sectors to be enabled */
    			Ul_SectorMask = FlashIntf_GetWriteSectorMask(FLASH_EEBANK, Ui_Addr, Ui_EndAddr);
    			if (Ul_SectorMask != 0LLU)
    			{
    				/* Enable the sectors to be written */
    				Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableEepromBankSectors((uint32_t)(Ul_SectorMask & FLASH_EESECMASK), (uint32_t)((Ul_SectorMask & FLASH_EESECMASK) >> 32U));
    				if (Enm_Ret == FLASHINTF_SUCCESS)
    				{
    					/* Wait for the operation to complete */
    					while ((FlashIntf_RetCode_t)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    					{
    					}
    
    					/* Iterate through the addresses in the FEE Bank */
    					while ((Ui_Addr < St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_BankAddr.Ui_EndAddr) && (Ui_Addr <= Ui_EndAddr))
    					{
    						/* Set the number of bytes to be written in the next operation */
    						Us_NWBytes = (FLASH_EEBANKWIDTH - (uint16_t)(Ui_Addr % FLASH_EEBANKWIDTH));
    						if (Us_NWBytes > Us_BufLen)
    						{
    							Us_NWBytes = Us_BufLen;
    						}
    
    						/* Write to the FEE address */
    						Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueProgrammingCommand((uint32_t *)Ui_Addr, Ptr_UcBuf, (uint8_t)Us_NWBytes, NULL, 0U, Fapi_AutoEccGeneration);
    						if (Enm_Ret != FLASHINTF_SUCCESS)
    						{
    							break;
    						}
    
    						/* Wait for the operation to complete */
    						while ((FlashIntf_RetCode_t)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    						{
    						}
    
    						/* Check whether the operation is successful */
    						if (FAPI_GET_FSM_STATUS != 0U)
    						{
    							Enm_Ret = FLASHINTF_FAIL;
    							break;
    						}
    
    						/* Update the buffer pointer, flash address and the number of bytes left for the next operation */
    						Ptr_UcBuf += Us_NWBytes;
    						Ui_Addr += Us_NWBytes;
    						Us_BufLen -= Us_NWBytes;
    					}
    				}
    			}
    		}
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_Write, ".TI.ramfunc");
    #endif
    /* Function to write data to the Flash and FEE Memory */
    FlashIntf_RetCode_t FlashIntf_Write(uint32_t Ui_Addr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_NULLPTR;
    
    	/* Validate the parameters passed */
    	if ((Ptr_UcBuf != NULL) && (Us_BufLen > 0U))
    	{
    		/* Call the appropriate function based on whether the address passed is in the Flash or the FEE */
    		if (Fapi_isAddressEEPROM(Ui_Addr))
    		{
    			Enm_Ret = FlashIntf_EEBankWrite(Ui_Addr, Ptr_UcBuf, Us_BufLen);
    		}
    		else
    		{
    			Enm_Ret = FlashIntf_MainBankWrite(Ui_Addr, Ptr_UcBuf, Us_BufLen);
    		}
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_GetEraseSectorMask, ".TI.ramfunc");
    #endif
    /* Function to retrieve the sectors to be enabled for a Flash/FEE erase operation */
    static uint64_t FlashIntf_GetEraseSectorMask(Fapi_FlashBankType Enm_Bank, uint32_t Ui_StartAddr, uint16_t *Ptr_UsNSectorsLeft, Fapi_FlashSectorType *Ptr_EnmFirstSector)
    {
    	uint64_t Ul_SectorMask = 0U;
    	Fapi_FlashSectorType Enm_SecIter;
    
    	/* Iterate through the sectors in the bank */
    	for (Enm_SecIter = Fapi_FlashSector0; Enm_SecIter < St_FDevInfo.St_ArrBankInfo[Enm_Bank].Ui_NSectors; Enm_SecIter++)
    	{
    		/* Identify the first sector */
    		if (Ul_SectorMask == 0U)
    		{
    			if ((Ui_StartAddr >= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_StartAddr)
    					&& (Ui_StartAddr <= St_FDevInfo.St_ArrBankInfo[Enm_Bank].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr))
    			{
    				Ul_SectorMask |= (uint64_t)((uint64_t)1U << Enm_SecIter);
    				*Ptr_EnmFirstSector = Enm_SecIter;
    			}
    		}
    		else
    		{
    			Ul_SectorMask |= (uint64_t)((uint64_t)1U << Enm_SecIter);
    		}
    
    		/* Update the number of sectors left */
    		if (Ul_SectorMask != 0U)
    		{
    			if (--(*Ptr_UsNSectorsLeft) == 0U)
    			{
    				break;
    			}
    		}
    	}
    
    	return Ul_SectorMask;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EraseMainBankSectors, ".TI.ramfunc");
    #endif
    /* Function to erase sectors in the Flash Memory */
    static FlashIntf_RetCode_t FlashIntf_EraseMainBankSectors(uint32_t Ui_StartAddr, uint16_t Us_NSectors)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_SUCCESS;
    	Fapi_FlashBankType Enm_BankIter;
    	uint16_t Us_SectorMask = 0U;
    	uint32_t Ui_Addr = Ui_StartAddr;
    	uint16_t Us_SectorsLeft = Us_NSectors;
    	Fapi_FlashSectorType Enm_SecIter = Fapi_FlashSector0;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Check whether the address range falls within the Flash Memory */
    	if ((Ui_StartAddr >= St_FDevInfo.St_FlashAddr.Ui_StartAddr) && (Ui_StartAddr <= St_FDevInfo.St_FlashAddr.Ui_EndAddr))
    	{
    		/* Iterate through the banks in the Flash */
    		for (Enm_BankIter = Fapi_FlashBank0; Enm_BankIter < St_FDevInfo.Us_NBanks; Enm_BankIter++)
    		{
    			/* Check whether the address falls within the bank */
    			if ((Ui_Addr >= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_StartAddr)
    					&& (Ui_Addr <= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr))
    			{
    				/* Set the bank to an active state */
    				Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(Enm_BankIter);
    				if (Enm_Ret == FLASHINTF_SUCCESS)
    				{
    					/* Retrieve the list of sectors to be enabled */
    					Us_SectorMask = (uint16_t)FlashIntf_GetEraseSectorMask(Enm_BankIter, Ui_Addr, &Us_SectorsLeft, &Enm_SecIter);
    					if (Us_SectorMask != 0U)
    					{
    						/* Enable the sectors to be erased */
    						Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableMainBankSectors(Us_SectorMask);
    						if (Enm_Ret == FLASHINTF_SUCCESS)
    						{
    							/* Wait for the operation to complete */
    							while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    							{
    							}
    
    							/* Iterate through the sectors in the Flash Bank */
    							for (; Us_NSectors > Us_SectorsLeft; Us_NSectors--)
    							{
    								/* Erase the Flash bank sector */
    								Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)Ui_Addr);
    								if (Enm_Ret != FLASHINTF_SUCCESS)
    								{
    									break;
    								}
    
    								/* Wait for the operation to complete */
    								while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    								{
    								}
    
    								/* Check whether the operation is successful */
    								if (FAPI_GET_FSM_STATUS != 0U)
    								{
    									Enm_Ret = FLASHINTF_FAIL;
    									break;
    								}
    
    								/* Update the flash address and the sector for the next operation */
    								Ui_Addr = (St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr + 1U);
    								Enm_SecIter++;
    							}
    						}
    					}
    				}
    			}
    
    			/* If an error is encountered or the erase operation is complete, exit the loop */
    			if ((Enm_Ret != FLASHINTF_SUCCESS) || (Us_NSectors == 0U))
    			{
    				break;
    			}
    		}
    	}
    	else
    	{
    	    Enm_Ret = FLASHINTF_INVADDR;
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EraseEEBankSectors, ".TI.ramfunc");
    #endif
    /* Function to erase sectors in the Flash EE Memory */
    static FlashIntf_RetCode_t FlashIntf_EraseEEBankSectors(uint32_t Ui_StartAddr, uint16_t Us_NSectors)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_INVADDR;
    	uint64_t Ul_SectorMask;
    	uint32_t Ui_Addr = Ui_StartAddr;
    	uint16_t Us_SectorsLeft = Us_NSectors;
    	Fapi_FlashSectorType Enm_SecIter = Fapi_FlashSector0;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Set the bank to an active state */
    	Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(FLASH_EEBANK);
    	if (Enm_Ret == FLASHINTF_SUCCESS)
    	{
    		/* Retrieve the list of sectors to be enabled */
    		Ul_SectorMask = FlashIntf_GetEraseSectorMask(FLASH_EEBANK, Ui_Addr, &Us_SectorsLeft, &Enm_SecIter);
    		if (Ul_SectorMask != 0LLU)
    		{
    			/* Enable the sectors to be erased */
    			Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableEepromBankSectors((uint32_t)(Ul_SectorMask & FLASH_EESECMASK), (uint32_t)((Ul_SectorMask & FLASH_EESECMASK) >> 32U));
    			if (Enm_Ret == FLASHINTF_SUCCESS)
    			{
    				/* Wait for the operation to complete */
    				while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    				{
    				}
    
    				/* Iterate through the sectors in the FEE Bank */
    				for (; Us_NSectors > Us_SectorsLeft; Us_NSectors--)
    				{
    					/* Erase the FEE bank sector */
    					Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)Ui_Addr);
    					if (Enm_Ret != FLASHINTF_SUCCESS)
    					{
    						break;
    					}
    
    					/* Wait for the operation to complete */
    					while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    					{
    					}
    
    					/* Check whether the operation is successful */
    					if (FAPI_GET_FSM_STATUS != 0U)
    					{
    						Enm_Ret = FLASHINTF_FAIL;
    						break;
    					}
    
    					/* Update the FEE address and the sector for the next operation */
    					Ui_Addr = (St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_ArrSecAddr[Enm_SecIter].Ui_EndAddr + 1U);
    					Enm_SecIter++;
    				}
    			}
    		}
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_Erase, ".TI.ramfunc");
    #endif
    /* Function to erase sectors in the Flash and FEE Memory */
    FlashIntf_RetCode_t FlashIntf_Erase(uint32_t Ui_Addr, uint16_t Us_NSectors)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_FAIL;
    
    	/* Validate the parameters passed */
    	if (Us_NSectors > 0U)
    	{
    		/* Call the appropriate function based on whether the address passed is in the Flash or the FEE */
    		if (Fapi_isAddressEEPROM(Ui_Addr))
    		{
    			Enm_Ret = FlashIntf_EraseEEBankSectors(Ui_Addr, Us_NSectors);
    		}
    		else
    		{
    			Enm_Ret = FlashIntf_EraseMainBankSectors(Ui_Addr, Us_NSectors);
    		}
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EraseMainBanks, ".TI.ramfunc");
    #endif
    /* Function to erase banks in the Flash and FEE Memory */
    static FlashIntf_RetCode_t FlashIntf_EraseMainBanks(uint32_t Ui_StartAddr, uint16_t Us_NBanks)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_SUCCESS;
    	Fapi_FlashBankType Enm_BankIter;
    	uint16_t Us_SectorMask;
    	uint32_t Ui_Addr = Ui_StartAddr;
    	Fapi_FlashSectorType Enm_SecIter;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Check whether the address range falls within the Flash Memory */
    	if ((Ui_StartAddr >= St_FDevInfo.St_FlashAddr.Ui_StartAddr) && (Ui_StartAddr <= St_FDevInfo.St_FlashAddr.Ui_EndAddr))
    	{
    		/* Iterate through the banks in the Flash */
    		for (Enm_BankIter = Fapi_FlashBank0; Enm_BankIter < St_FDevInfo.Us_NBanks; Enm_BankIter++)
    		{
    			/* Check whether the address falls within the bank */
    			if ((Ui_Addr >= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_StartAddr)
    					&& (Ui_Addr <= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr))
    			{
    				/* Set the bank to an active state */
    				Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(Enm_BankIter);
    				if (Enm_Ret == FLASHINTF_SUCCESS)
    				{
    					/* Set the sectors in the bank to be enabled */
    					for (Enm_SecIter = Fapi_FlashSector0; Enm_SecIter < St_FDevInfo.St_ArrBankInfo[Enm_BankIter].Ui_NSectors; Enm_SecIter++)
    					{
    						Us_SectorMask |= (uint16_t)((uint16_t)1U << Enm_SecIter);
    					}
    
    					/* Enable all the bank sectors for erase operation */
    					Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableMainBankSectors(Us_SectorMask);
    					if (Enm_Ret == FLASHINTF_SUCCESS)
    					{
    						/* Wait for the operation to complete */
    						while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    						{
    						}
    
    						/* Erase the Flash Bank */
    						Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueAsyncCommandWithAddress(Fapi_EraseBank, (uint32_t *)Ui_Addr);
    						if (Enm_Ret != FLASHINTF_SUCCESS)
    						{
    							break;
    						}
    
    						/* Wait for the operation to complete */
    						while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    						{
    						}
    
    						/* Check whether the operation is successful */
    						if (FAPI_GET_FSM_STATUS != 0U)
    						{
    							Enm_Ret = FLASHINTF_FAIL;
    							break;
    						}
    
    						/* Update the flash address and number of banks left for the next erase operation */
    						Ui_Addr = St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr + 1U;
    						--Us_NBanks;
    					}
    				}
    			}
    
    			/* If an error is encountered or the erase operation is complete, exit the loop */
    			if ((Enm_Ret != FLASHINTF_SUCCESS) || (Us_NBanks == 0U))
    			{
    				break;
    			}
    		}
    	}
    	else
    	{
    	    Enm_Ret = FLASHINTF_INVADDR;
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EraseEEBank, ".TI.ramfunc");
    #endif
    /* Function to erase the FEE Memory Bank */
    static FlashIntf_RetCode_t FlashIntf_EraseEEBank(uint32_t Ui_Addr)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_INVADDR;
    	uint64_t Ul_SectorMask;
    	Fapi_FlashSectorType Enm_SecIter;
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Set the bank to an active state */
    	Enm_Ret = (FlashIntf_RetCode_t)Fapi_setActiveFlashBank(FLASH_EEBANK);
    	if (Enm_Ret == FLASHINTF_SUCCESS)
    	{
    		/* Set the sectors in the bank to be enabled */
    		for (Enm_SecIter = Fapi_FlashSector0; Enm_SecIter < St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].Ui_NSectors; Enm_SecIter++)
    		{
    			Ul_SectorMask |= (uint64_t)((uint64_t)1U << Enm_SecIter);
    		}
    
    		/* Enable all the bank sectors for erase operation */
    		Enm_Ret = (FlashIntf_RetCode_t)Fapi_enableEepromBankSectors((uint32_t)(Ul_SectorMask & FLASH_EESECMASK), (uint32_t)((Ul_SectorMask & FLASH_EESECMASK) >> 32U));
    		if (Enm_Ret == FLASHINTF_SUCCESS)
    		{
    			/* Wait for the operation to complete */
    			while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    			{
    			}
    
    			/* Erase the FEE Bank */
    			Enm_Ret = (FlashIntf_RetCode_t)Fapi_issueAsyncCommandWithAddress(Fapi_EraseBank, (uint32_t *)Ui_Addr);
    			if (Enm_Ret == FLASHINTF_SUCCESS)
    			{
    				/* Wait for the operation to complete */
    				while ((Fapi_StatusType)FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
    				{
    				}
    
    				/* Check whether the operation is successful */
    				if (FAPI_GET_FSM_STATUS != 0U)
    				{
    					Enm_Ret = FLASHINTF_FAIL;
    				}
    			}
    		}
    	}
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EraseBanks, ".TI.ramfunc");
    #endif
    /* Function to erase banks in the Flash and FEE Memory */
    FlashIntf_RetCode_t FlashIntf_EraseBanks(uint32_t Ui_Addr, uint16_t Us_NBanks)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_FAIL;
    
    	/* Validate the parameters passed */
    	if ((Us_NBanks > 0U) && (Us_NBanks <= St_FDevInfo.Us_NBanks))
    	{
    		/* Call the appropriate function based on whether the address passed is in the Flash or the FEE */
    		if (Fapi_isAddressEEPROM(Ui_Addr))
    		{
    			Enm_Ret = FlashIntf_EraseEEBank(Ui_Addr);
    		}
    		else
    		{
    			Enm_Ret = FlashIntf_EraseMainBanks(Ui_Addr, Us_NBanks);
    		}
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_MainBankRead, ".TI.ramfunc");
    #endif
    /* Function to read data from the Main Flash Memory */
    static FlashIntf_RetCode_t FlashIntf_MainBankRead(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_SUCCESS;
    	Fapi_FlashBankType Enm_BankIter;
    	uint32_t Ui_EndAddr = (Ui_StartAddr + Us_BufLen - 1U);
    	uint32_t Ui_Addr = Ui_StartAddr;
    	uint32_t Ui_NRBytes;
    
    	/* Check whether the address range falls within the Flash Memory */
    	if ((Ui_StartAddr >= St_FDevInfo.St_FlashAddr.Ui_StartAddr) && (Ui_EndAddr <= St_FDevInfo.St_FlashAddr.Ui_EndAddr))
    	{
    		/* Iterate through the banks in the Flash */
    		for (Enm_BankIter = Fapi_FlashBank0; Enm_BankIter < St_FDevInfo.Us_NBanks; Enm_BankIter++)
    		{
    			/* Check whether the address falls within the bank */
    			if ((Ui_Addr >= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_StartAddr)
    					&& (Ui_Addr <= St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr))
    			{
    				/* Iterate through the addresses in the Flash Bank */
    				if ((Ui_Addr < St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr) && (Ui_Addr <= Ui_EndAddr))
    				{
    					/* Set the number of bytes to be read in the next operation */
    					if (Ui_EndAddr > St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr)
    					{
    						Ui_NRBytes  = (St_FDevInfo.St_ArrBankInfo[Enm_BankIter].St_BankAddr.Ui_EndAddr - Ui_Addr + 1U);
    					}
    					else
    					{
    						Ui_NRBytes = Us_BufLen;
    					}
    
    					/* Read from the Flash address */
    					Enm_Ret = (FlashIntf_RetCode_t)Fapi_doMarginReadByByte((uint8_t *)Ui_Addr, Ptr_UcBuf, Ui_NRBytes, Fapi_NormalRead);
    					if (Enm_Ret != FLASHINTF_SUCCESS)
    					{
    						break;
    					}
    
    					/* Update the buffer pointer, flash address and the number of bytes left for the next operation */
    					Ptr_UcBuf += Ui_NRBytes;
    					Ui_Addr += Ui_NRBytes;
    					Us_BufLen -= Ui_NRBytes;
    				}
    			}
    
    			/* If an error is encountered or the read operation is complete, exit the loop */
    			if ((Enm_Ret != FLASHINTF_SUCCESS) || (Us_BufLen == 0U))
    			{
    				break;
    			}
    		}
    	}
    	else
    	{
    	    Enm_Ret = FLASHINTF_INVADDR;
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_EEBankRead, ".TI.ramfunc");
    #endif
    /* Function to read data from the Flash EEPROM Memory */
    static FlashIntf_RetCode_t FlashIntf_EEBankRead(uint32_t Ui_StartAddr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_INVADDR;
    	uint32_t Ui_EndAddr = (Ui_StartAddr + Us_BufLen - 1U);
    
    	/* Check whether the address range falls within the FEE Bank */
    	if ((Ui_StartAddr >= St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_BankAddr.Ui_StartAddr) && (Ui_EndAddr <= St_FDevInfo.St_ArrBankInfo[FLASH_EEBANK].St_BankAddr.Ui_EndAddr))
    	{
    		/* Read from the FEE address */
    		Enm_Ret = (FlashIntf_RetCode_t)Fapi_doMarginReadByByte((uint8_t *)Ui_StartAddr, Ptr_UcBuf, (uint32_t)Us_BufLen, Fapi_NormalRead);
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_Read, ".TI.ramfunc");
    #endif
    /* Function to read data from the Flash and FEE Memory */
    FlashIntf_RetCode_t FlashIntf_Read(uint32_t Ui_Addr, uint8_t *Ptr_UcBuf, uint16_t Us_BufLen)
    {
    	FlashIntf_RetCode_t Enm_Ret = FLASHINTF_NULLPTR;
    
    	/* Validate the parameters passed */
    	if ((Ptr_UcBuf != NULL) && (Us_BufLen > 0U))
    	{
    		/* Call the appropriate function based on whether the address passed is in the Flash or the FEE */
    		if (Fapi_isAddressEEPROM(Ui_Addr))
    		{
    			Enm_Ret = FlashIntf_EEBankRead(Ui_Addr, Ptr_UcBuf, Us_BufLen);
    		}
    		else
    		{
    			Enm_Ret = FlashIntf_MainBankRead(Ui_Addr, Ptr_UcBuf, Us_BufLen);
    		}
    	}
    
    	return Enm_Ret;
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_ClrFSMStatus, ".TI.ramfunc");
    #endif
    /* Function to clear FSM status */
    FlashIntf_RetCode_t FlashIntf_ClrFSMStatus(void)
    {
    	return (FlashIntf_RetCode_t)Fapi_issueAsyncCommand(Fapi_ClearStatus);
    }
    
    
    #ifdef FLASH_MOVE_TO_RAM
    /* Pragma directive for moving code to RAM */
    #pragma CODE_SECTION(FlashIntf_GetFSMStatus, ".TI.ramfunc");
    #endif
    /* Function to retrieve FSM status */
    FlashIntf_RetCode_t FlashIntf_GetFSMStatus(void)
    {
    	/* Return current FSM status */
    	return (FlashIntf_RetCode_t)FAPI_GET_FSM_STATUS;
    }
    

  • /*******************************************************************************
    ** Copyright (c) 2022 KPTL
    **
    ** This software is the property of KPTL.
    ** It can not be used, duplicated and/or distributed without the express
    ** permission of KPTL.
    **
    ** -----------------------------------------------------------------------------
    ** File Name    : FlashToRam.c
    ** Module Name  : Flash-to-RAM BSW Source File
    ** -----------------------------------------------------------------------------
    **
    ** Description : To implement routines that load code that operates on Flash
    **               into RAM memory
    **
    ** This file must exclusively contain information needed to
    ** use this component.
    **
    ********************************************************************************
    ** R E V I S I O N  H I S T O R Y
    ********************************************************************************
    ** V01.00 24/02/2022    Initial Creation
    ********************************************************************************/
    #include <string.h>
    
    #include "system.h"
    #include "sys_core.h"
    
    #include "SysUtil.h"
    
    #include "FlashIntf.h"
    #include "FlashIntf_Cfg.h"
    #include "FlashToRam.h"
    
    
    #ifdef FLASH_MOVE_TO_RAM
    
    extern uint32_t RamfuncsLoadStart;
    extern uint32_t RamfuncsLoadSize;
    extern uint32_t RamfuncsRunStart;
    
    void FlashToRam_CopyCode(void)
    {
    	/* Copy functions from Flash To RAM */
    	memcpy((void *)&RamfuncsRunStart, (const void *)&RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    
    	/* Ensure pipeline consistency (recommended) */
        /* Flush the processor pipeline */
        SysUtil_flushPipeline();
    
    	/* Disable Interrupts */
    	_disable_IRQ_interrupt_();
    
    	/* Set the fallback power mode for the Flash Banks */
    	flashWREG->FBFALLBACK = ((flashWREG->FBFALLBACK & FLASH_FBFALLBACK_MASK) | FLASH_FBFALLBACK);
    
    	/* Set the Flash Charge Pump Fallback Power Mode */
    	flashWREG->FPAC1 = ((flashWREG->FPAC1 & FLASH_FPAC1_MASK) | FLASH_FPAC1);
    
    	/* Disable pipeline mode and address setup wait state and set wait states for Flash Operation */
    	flashWREG->FRDCNTL = ((flashWREG->FRDCNTL & FLASH_FRDCNTL_MASK) | ((uint32_t)FLASH_RWAIT << FLASH_RWAIT_SHIFT));
    
    	/* Set wait states for FEE Operation */
    	flashWREG->FSMWRENA = 0x5U;
    	flashWREG->EEPROMCONFIG = ((flashWREG->EEPROMCONFIG & FLASH_EEPROMCONFIG_MASK) | ((uint32_t)FLASH_EWAIT << FLASH_EWAIT_SHIFT));
    	flashWREG->FSMWRENA = 0x2U;
    
    	/* Enable pipeline mode and and address setup wait state for Flash Operation */
    	flashWREG->FRDCNTL |= FLASH_FRDCNTL;
    
    	/* Enable Interrupts */
    	_enable_interrupt_();
    }
    
    void SysUtil_flushPipeline(void)
    {
        __asm(" dsb");      // Data Synchronization Barrier
        __asm(" isb");      // Instruction Synchronization Barrier
    }
    #endif
    

  • Hi Prajakta,

    Thank you for sharing your linker command file, and  FlashIntf.c/FlashToRam.c files.


    Root Cause (Confirmed from Your Files)

    Your UNDEF interrupt crash at Fapi_setActiveFlashBank() occurs because the F021 Flash API is still executing from flash memory when it tries to modify that same flash bank. The TMS570LS0914 is a single-bank device — all flash resides in Bank 0. There is no separate Bank 1 for program flash, so you cannot work around this by switching banks. Your write address 0x000E0000 falls within sector 13 of Bank 0 and is valid.


    What Your Files Currently Do and What Is Wrong

    Linker File (1682.Linker_cmd.txt) 1682.Linker_cmd.txt

    Your current .TI.ramfunc section reads:

    .TI.ramfunc align(32) : { -l F021_API_CortexR4_BE_V3D16.lib(.text) }
    LOAD=FLASH0, RUN=RAM,
    LOAD_START(RamfuncsLoadStart),
    RUN_START(RamfuncsRunStart),
    SIZE(RamfuncsLoadSize)

    There are two problems here:

    1. Only the F021 library itself is included in .TI.ramfunc — your own FlashIntf.c and FlashToRam.c object files are not listed. They will be placed by the general .text : {} > FLASH0 line and will execute from flash, not RAM.

    2. Only .text is captured from the F021 library — the .data section is missing. Some API object files carry initialized data that must also be relocated to RAM.

    FlashIntf.c FlashIntf.c

    Your code already uses the #pragma CODE_SECTION directive correctly on all flash interface functions, for example:

    #pragma CODE_SECTION(FlashIntf_Init, ".TI.ramfunc");
    #pragma CODE_SECTION(FlashIntf_MainBankWrite, ".TI.ramfunc");

    However, every one of these directives is wrapped in an #ifdef FLASH_MOVE_TO_RAM guard. If FLASH_MOVE_TO_RAM is not defined in your build configuration, all pragma directives are compiled out and none of your functions will be placed in .TI.ramfunc, regardless of your linker settings. Please verify this macro is defined in your project.

    FlashToRam.c FlashToRam.c

    Your FlashToRam_CopyCode() function is correct as written. The memcpy, pipeline flush (DSB + ISB barriers), and flash wait state configuration (FRDCNTL, EEPROMCONFIG) are all implemented properly. The issue is not in this file.


    Exact Changes Required

    Fix 1 — Update Your Linker .cmd File 1682.Linker_cmd.txt

    Replace your current .TI.ramfunc section with the following:

    .TI.ramfunc align(32) :
    {
        -l F021_API_CortexR4_BE_V3D16.lib (.text, .data)
        FlashIntf.obj  (.text, .data)
        FlashToRam.obj (.text, .data)
    } LOAD=FLASH0, RUN=RAM,
      LOAD_START(RamfuncsLoadStart),
      RUN_START(RamfuncsRunStart),
      SIZE(RamfuncsLoadSize)
    This section must remain before the general .text : {} > FLASH0 line in your SECTIONS block.

    Fix 2 — Confirm FLASH_MOVE_TO_RAM is Defined FlashIntf.c

    In your project's predefined symbols or compiler options, confirm that FLASH_MOVE_TO_RAM is defined. Without it, the #pragma CODE_SECTION directives in FlashIntf.c are compiled out entirely.

    Fix 3 — Verify Startup Call Order FlashToRam.c

    FlashToRam_CopyCode() must be called before any Fapi_ function, including FlashIntf_Init(). Confirm your startup sequence is:

    FlashToRam_CopyCode(); // Must execute first
    FlashIntf_Init(); // Then initialize flash banks

    Additional Checks

    Requirement
    Status from Your Files
    Action Needed
    Interrupts disabled during flash ops
    Correctly implemented in FlashIntf.c
    None
    Pipeline flush after RAM copy
    Correctly implemented in FlashToRam.c
    None
    Flash wait states (RWAIT/EWAIT)
    Configured in FlashToRam.c
    Verify FLASH_RWAIT and FLASH_EWAIT values in FlashIntf_Cfg.h are correct for your HCLK
    HCLK passed to Fapi_initializeFlashBanks()
    Uses HCLK_FREQ macro
    Confirm HCLK_FREQ matches your actual clock frequency in FlashIntf_Cfg.h
    Privilege mode
    Cannot verify from provided files
    Confirm code is running in supervisor mode, not user mode
    Library endianness
    Linker references _BE variant
    Confirm your build is configured for Big Endian

    Summary

    1. Linker .cmd: Add .data to the F021 library entry and add FlashIntf.obj and FlashToRam.obj explicitly to .TI.ramfunc
    2. Build settings: Confirm FLASH_MOVE_TO_RAM is defined as a preprocessor symbol
    3. FlashToRam.c: No changes needed
    4. FlashIntf.c: No changes needed, provided Fix 2 is confirmed
    5. Verify HCLK_FREQ, FLASH_RWAIT, and FLASH_EWAIT values in your configuration header

    Please make these changes and let us know if the crash persists. If it does, please share the value of HCLK_FREQ from FlashIntf_Cfg.h and confirm whether FLASH_MOVE_TO_RAM was defined in your build.

    Best Regards,

    Zackary Fleenor

  • Hello Zackary Fleenor,

    Thank you very much for your support. 

    I understood the issues very clearly now.

    1. I have done the linker command file changes as suggested. but code gets crash after FlashToRam_CopyCode(); function. It goes to prefetchEntry . When I comment both object files, code gets executed smoothly.

    2. FLASH_MOVE_TO_RAM this macro is defined in FlashIntf.h which was not shared with you.

    3. HCLK_FREQ = 160, FLASH_RWAIT  = 3, FLASH_EWAIT = 9

    4. Privilege mode : how to confirm this whether code is running in supervisor mode ?

    5. Library endianness is configured as big endian.

    6. start up call order is same as you mentioned.

    Thanks,

    Prajakta

  • In addition to above debugs,

    1. I have also found that commenting  FlashToRam.obj (.text, .data) will also work.

    2. If I uncomment this, codes get executed wrongly. the control jumps to SysUtil_flushPipeline() line no 75 after finishing execution of FlashToRam_CopyCode().

    3. code starts executing SysUtil_flushPipeline(), after this it goes to view disassembly. 

    4. I did not debug step by step after flashing completed and just run the code, then code stucks at prefetchEntry .

    so the suspect is FlashToRam_CopyCode() function or something related to this.

    Kindly help me to get out of this.

    thanks,

    Prajakta

  • Hi Prajakta,

    Your new crash is a different problem from the original UNDEF interrupt — and the fix is straightforward.

    Remove FlashToRam.obj from the .TI.ramfunc section entirely. Only FlashIntf.obj and the F021 library should be placed there.

    The reason: FlashToRam_CopyCode() is the function that performs the copy from flash to RAM. When you include FlashToRam.obj in .TI.ramfunc, the linker assigns it a run address in RAM — but this function must execute before the copy happens, while it still physically resides in flash. You're creating a circular dependency: the code responsible for copying itself to RAM cannot execute from RAM because it hasn't been copied yet [1][2].

    After FlashToRam_CopyCode() completes the memcpy and executes the pipeline flush (DSB + ISB in SysUtil_flushPipeline()), the CPU attempts to fetch the next instruction from the RAM run address that the linker assigned — but since the function was already executing from flash, the program counter jumps to an invalid location, causing the prefetch abort [3][4].

    Corrected Linker .TI.ramfunc Section

    Your .TI.ramfunc section should look like this:

    .TI.ramfunc align(32) :
    {
        FlashIntf.obj (.text, .data)
        -l F021_API_CortexR4_BE_V3D16.lib (.text, .data)
    }
    LOAD = FLASH0, RUN = RAM,
    LOAD_START(RamfuncsLoadStart),
    RUN_START(RamfuncsRunStart),
    SIZE(RamfuncsLoadSize)

    Do NOT include FlashToRam.obj — it must remain in the general .text : {} > FLASH0 section so it executes from flash and can safely copy the other objects to RAM.

    Why This Works

    Object
    Where it executes
    Why
    FlashToRam.obj
    Flash
    It performs the RAM copy — must run before copy completes
    FlashIntf.obj
    RAM
    It calls F021 API functions that operate on flash
    F021_API_CortexR4_BE_V3D16.lib
    RAM
    Cannot execute from the same bank it modifies [1]

    Regarding Privilege Mode

    To confirm you're in supervisor mode, read the CPSR register's mode bits [4:0] in the debugger. At the point where you call FlashIntf_Init():

    • 0x13 = Supervisor mode ✓
    • 0x10 = User mode ✗ (will fail)

    If you're using HALCoGen-generated startup code without an OS, you're likely already in supervisor mode by default.

    Summary of Actions

    1. Remove FlashToRam.obj (.text, .data) from .TI.ramfunc
    2. Keep FlashIntf.obj (.text, .data) and the F021 library in .TI.ramfunc
    3. Your HCLK_FREQ = 160, FLASH_RWAIT = 3, FLASH_EWAIT = 9 values are correct for 160 MHz
    4. FLASH_MOVE_TO_RAM is confirmed defined — no issue there
    5. Startup order is confirmed correct

    This should resolve both the prefetch abort and the original UNDEF interrupt issue.


    1. TMS570LS0914: F021 API on TMS570LS0914PGE - TI E2E
    2. TMS570LS0914: CAN Bootloader Issue - TI E2E
    3. TMS570LS0x Technical Reference Manual - Prefetch Aborts (SPNU607A)
    4. Hercules ARM Cortex-R Exception Handling (SPNA236)

    Best Regards,

    Zackary Fleenor

  • Thank you for your support