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.

Prefetch entry when using flash api

Other Parts Discussed in Thread: TMS570LS1224, HALCOGEN

Hi,

I am using flash api v2.1.1 with the TMS570ls1224.  If I step through my code I can flash data OK, but if I just let it run I get a prefetch entry.  Any idea what could cause this?

 

In my Halcogen configuration I have pipeline mode and 3 data wait states.  These were the default values so I haven't changed them.

What is the difference between pipeline and normal mode?  I tried to change to normal mode to see if it makes a difference, but Halcogen changes it back to pipeline.

[EDIT] This was consistently working when I stepped through, but not when I ran.  Now I see the prefetch error all the time.  I think I am doing all the initialization needed, and the values being passed into the functions (I've tried writing and erasing) are valid.  What would cause a prefetch entry when making a call to either 

Fapi_issueProgrammingCommand or Fapi_issueAsyncCommandWithAddress

 

Thanks,

David

 

static void handleFlashWrite(CmdFmt_Obj *pCmd, RspFmt_Obj *pRsp)
{
	uint32_t	startAddr;
	uint32_t	startProgAddr;
	uint32_t	sizeInBytes;
	uint32_t	bytesRemain;
	uint8_t 	*pData;
	uint8_t		*checkData;
	uint32_t bytes = 0;
	uint8_t sectorIndex = 0;
	uint8_t bank = 0;
	Fapi_StatusType fapiStatus = Fapi_Error_InvalidBank; //Init to an error

    // visually indicate progress for diag output
    diagPrintf("%s", BOOT_INDICATION_SYMBOL);

	// misc init
	startAddr = pCmd->params[0];
	startProgAddr = startAddr;
	sizeInBytes = pCmd->params[1];
	pData = (uint8_t *)&pCmd->params[2];
	checkData = pData;
	bytesRemain = sizeInBytes;

	//Set the status to an error.  if we get all the way through, then we will set it OK
	pRsp->status = ERR_BURNING_FLASH;

	//Check the size to be flashed
	if (sizeInBytes < 16)
	{
		bytes = sizeInBytes;
	}
	else
	{
		bytes = 16;
	}

	//Find the bank to flash. Note, this should always be bank 0, but was put in for portability.
	for (sectorIndex = 0; sectorIndex < NUMBEROFSECTORS - 1; sectorIndex++)
	{
		if (startAddr < (uint32_t)(flash_sector[sectorIndex+1].start))
		{
			bank = flash_sector[sectorIndex].bankNumber;

			//We have the bank, so get out of the for loop
		    sectorIndex = NUMBEROFSECTORS;
		}
	}

	//Initialize the flash banks
	fapiStatus = Fapi_initializeFlashBanks(HCLK_FREQ);

	if(fapiStatus == Fapi_Status_Success)
	{
		//Set the bank we are flashing as active
		fapiStatus = Fapi_setActiveFlashBank((Fapi_FlashBankType)bank);

		if(fapiStatus == Fapi_Status_Success)
		{
			//Enable the sectors to be flashed
			fapiStatus = Fapi_enableMainBankSectors(ENABLE_ALL_SECTORS);

			if(fapiStatus == Fapi_Status_Success)
			{
				while(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy){};

				//TODO bytes needs to be a multiple of 8 because ECC generation is done on 64 bits
 				while((bytesRemain > 0) && (fapiStatus == Fapi_Status_Success))
				{
					fapiStatus = Fapi_issueProgrammingCommand((uint32_t *)startProgAddr,
															  (uint8_t *)pData,
															  (uint8_t)bytes,
															  0,
															  0,
															  Fapi_DataOnly); //TODO change to Fapi_AutoEccGeneration

					while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );

					startProgAddr += bytes;
					pData += bytes;
					bytesRemain -= bytes;

					if(bytesRemain < 16)
					{
						bytes = bytesRemain;
					}
				}



 				if(fapiStatus == Fapi_Status_Success)
 				{
 					pRsp->status = checkFlashProgram(startAddr, (uint32_t)&checkData, sizeInBytes);
 				}
			}
		}
	}
}

  • Hi David,

    Can you please change the code to check the fapiStatus in the while loop just before "startProgAddr += bytes;"? You can add breakpoints to find which statement causes the error. It would be helpful to know which line causes the problem.

    Regards,
    QJ
  • Hi QJ,

    I can add that, but the program doesn't get there. I can step through the code up until the call to Fapi_issueProgrammingCommand, and that call is what triggers the prefetch error.

    David
  • David,

    Can you verify that the "startProgAddr" is at a 16 byte boundary?

    Joe
  • Hi,

    My bootloader resides in the first 6 sectors of flash, so I am trying to write to the first sector that would be my main app, which starts at address 0x00020000.

    I also have an erase function (set up to erase sectors 7-15.)  If I step through it will erase 2 sectors OK, but on the third (or if I just let it run) I get a prefetch error on the call to Fapi_issueAsyncCommandWithAddress.  (function  code below).  I have checked the Fapi status, and all the values it increments/decrements and they look OK.

    I'm wondering if there is some set up or initialization I am missing or done wrong.  I have the api in my linker file (below), also, the first thing I do in my main app is  copy the api to RAM.   Is anything else needed?

    Linker file / code to copy api to RAM

    --retain="*(.intvecs)"
    
    
    /*----------------------------------------------------------------------------*/
    /* Memory Map                                                                 */
    
    MEMORY
    {
        VECTORS 	(X)  : origin=0x00000000 length=0x00000020
        FLASH_API  	(RX) : origin=0x00000020 length=0x000014E0
        FLASH0  	(RX) : origin=0x00001500 length=0x0001EB00
        STACKS  	(RW) : origin=0x08000000 length=0x00003500
        RAM     	(RW) : origin=0x08003500 length=0x0002cb00
    
    }
    
    
    /*----------------------------------------------------------------------------*/
    /* Section Configuration                                                      */
    
    SECTIONS
    {
        .intvecs : {} > VECTORS
        flashAPI :
        {
         --library= F021_API_CortexR4_BE.lib < FlashStateMachine.IssueFsmCommand.obj
         									  FlashStateMachine.SetActiveBank.obj
         									  FlashStateMachine.InitializeFlashBanks.obj
         									  FlashStateMachine.EnableMainSectors.obj
         									  FlashStateMachine.IssueFsmCommand.obj
         									  FlashStateMachine.ScaleFclk.obj
                                              Init.obj
                                              Utilities.CalculateEcc.obj
                                              Utilities.WaitDelay.obj
                                              Utilities.CalculateFletcher.obj
                                              Read.MarginByByte.obj
                                              Read.Common.obj
                                              Read.FlushPipeline.obj
         									  Read.WdService.obj
                                              Async.WithAddress.obj
                                              Program.obj > (.text)
       } load = FLASH_API, run = RAM, LOAD_START(api_load), RUN_START(api_run), SIZE(api_size)
    
        .text    : {} > FLASH0 
        .const   : {} > FLASH0 
        .cinit   : {} > FLASH0 
        .pinit   : {} > FLASH0
        FEE_TEXT_SECTION : {} > FLASH0
        FEE_CONST_SECTION : {} > FLASH0
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
        FEE_DATA_SECTION : {} > RAM
    
    }
    
    
    
        .text
        .arm
    ;-------------------------------------------------------------------------------
    ;
    ; Copy the Flash API from flash to SRAM.
    ;
    
        .def     _copyAPI2RAM_
        .asmfunc
    
    _copyAPI2RAM_
    
       .ref    api_load
    flash_load   .word api_load
       .ref    api_run
    flash_run   .word api_run
        .ref    api_size
    flash_size  .word api_size
    
         ldr    r0, flash_load
         ldr    r1, flash_run
         ldr    r2, flash_size
         add    r2, r1, r2
    copy_loop1:
         ldr     r3, [r0], #4
         str     r3, [r1], #4
         cmp     r1, r2
         blt     copy_loop1
          bx     lr
    
        .endasmfunc

    Function to erase flash

    static void handleFlashPrepare(CmdFmt_Obj *pCmd, RspFmt_Obj *pRsp)
    {
    	uint32_t startAddress = PROGRAMFLASH_BEGIN_ADDRESS;
    	uint32_t sectorIndex = 0;
    	uint8_t bankIndex = 0;
    	uint32_t eraseIndex;
    	uint8_t startBank;
    	uint8_t	startSector;
    	uint8_t endBank = 0;
    	uint32_t *eraseStartAddrCheck;
    	uint32_t *eraseStartAddr;
    	bool endLoop = FALSE;
        int  remaining;
        uint32_t endAddress;
        uint32_t length;
        Fapi_StatusType fapiStatus = Fapi_Error_InvalidBank; //Init to an error
    
        // for diag output
        alreadyPrintedHeader = FALSE;
    
    	eraseStartAddrCheck = (uint32_t *)startAddress;
    	eraseStartAddr = (uint32_t *)startAddress;
    
    	length = ((PROGRAMFLASH_END_ADDRESS - PROGRAMFLASH_BEGIN_ADDRESS) + 1);
    	endAddress = startAddress + length;
    
    	for (sectorIndex = 0; (sectorIndex < NUMBEROFSECTORS - 1) && (endLoop == FALSE); sectorIndex++)
    	{
    		if (startAddress == (uint32_t)(flash_sector[sectorIndex].start))
    		{
    			startBank     = flash_sector[sectorIndex].bankNumber;
    		    startSector   = flash_sector[sectorIndex].sectorNumber;
    		    eraseStartAddrCheck = flash_sector[sectorIndex].start;
    		    eraseStartAddr  = flash_sector[sectorIndex].start;
    
    		    endLoop = TRUE;
    		}
    	}
    
    	//Reset endLoop variable before the next loop
    	endLoop = FALSE;
    
    	for (sectorIndex = startSector; (sectorIndex < NUMBEROFSECTORS - sectorIndex) && (endLoop == FALSE); sectorIndex++)
    	{
    		if (endAddress <= ((uint32_t)(flash_sector[sectorIndex].start) + flash_sector[sectorIndex].length))
    		{
    			endBank  = flash_sector[sectorIndex].bankNumber;
    			endLoop = TRUE;
    		}
    	}
    
    	fapiStatus = Fapi_initializeFlashBanks(HCLK_FREQ);
    
    	if(fapiStatus == Fapi_Status_Success)
    	{
    		for (bankIndex = startBank; (bankIndex < endBank + 1) && (fapiStatus == Fapi_Status_Success); bankIndex++)
    		{
    			fapiStatus = Fapi_setActiveFlashBank((Fapi_FlashBankType)bankIndex);
    
    			if(fapiStatus == Fapi_Status_Success)
    			{
    				if (bankIndex == 0)
    				{
    					eraseIndex = startSector;
    					remaining = length;
    				}
    				else
    				{
    					eraseIndex = 0;
    				}
    
    				fapiStatus = Fapi_enableMainBankSectors(ENABLE_ALL_SECTORS);
    
    				while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ){};
    
    				if(fapiStatus == Fapi_Status_Success)
    				{
    					do
    					{
    						fapiStatus = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, eraseStartAddr);
    
    						while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ){};
    
    						remaining -= flash_sector[eraseIndex++].length;
    						eraseStartAddr = flash_sector[eraseIndex].start;
    
    					}while((remaining > 0) && ( eraseIndex < flash_bank[bankIndex].numOfSectors) && (fapiStatus == Fapi_Status_Success));
    				}
    			}
    		}
    	}
    
    	 pRsp->status = flashEraseCheck((uint32_t)eraseStartAddrCheck, length);
    }
    

  • Hi David,

    What is the value of ENABLE_ALL_SECTORS in your code? If you enable all the sectors, it should be 0x7FFF.

    BTW, do you have Flash Library 2.01.00? The bootloader was tested using this lib API. I haven't tested the boartloader under 2.01.01.

    If you are not sure if you missed any obj file in your cmd file, you can use: --library= F021_API_CortexR4_BE.lib (.text) instead of listing all the obj files in CMD file.

    Regards,
    QJ
  • Hi QJ,

    ENABLE_ALL_SECTORS is set to 0xFFFF for sectors 0-15 in bank 0.
     
    I am using flash lib 2.1.1. I can try using 2.1.0 and see if this changes the behavior.
     
     So my new linker file should look something like:

     

    --retain="*(.intvecs)"
    
    
    /*----------------------------------------------------------------------------*/
    /* Memory Map                                                                 */
    
    MEMORY
    {
        VECTORS 	(X)  : origin=0x00000000 length=0x00000020
        FLASH_API  	(RX) : origin=0x00000020 length=0x000014E0
        FLASH0  	(RX) : origin=0x00001500 length=0x0001EB00
        STACKS  	(RW) : origin=0x08000000 length=0x00003500
        RAM     	(RW) : origin=0x08003500 length=0x0002cb00
    
    }
    
    
    /*----------------------------------------------------------------------------*/
    /* Section Configuration                                                      */
    
    SECTIONS
    {
        .intvecs : {} > VECTORS
        flashAPI :
        {
         --library= F021_API_CortexR4_BE.lib (.text)
        } load = FLASH_API, run = RAM, LOAD_START(api_load), RUN_START(api_run), SIZE(api_size)
    
        .text    : {} > FLASH0 
        .const   : {} > FLASH0 
        .cinit   : {} > FLASH0 
        .pinit   : {} > FLASH0
        FEE_TEXT_SECTION : {} > FLASH0
        FEE_CONST_SECTION : {} > FLASH0
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
        FEE_DATA_SECTION : {} > RAM
    
    }


     
    Thanks,
    David

  • Assuming I modified the linker file correctly, it didn't affect the behavior, but I do like not needing to list all of the files.

    Using Flash api 2.1.0 helped in the sense that if I step through the write function, I can successfully write to flash. However, it will still only erase 2 sectors (it does it successfully, I can see it erase the data that I wrote) before I get a prefetch error. It seems like it will erase any two sectors, but only 2.

     

    However, for both writing and erasing, if I just let the program run I get the prefetch error, I have to step over the flash api program and erase commands for them to work.

     

    Also, it looks like the FEE code generated by Halcogen 4.3 is not compatible with flash API 2.1.0.  I get an error in ti_fee_util.c when building, specifically on FAPI_SUSPEND_FSM; in TI_Fee_SuspendResumeErase().  That macro is defined in Helpers.h of the flash API.  Using the Helpers.h file from flash api 2.1.1 builds without error, but then there seems to be an error with the define for FAPI_CHECK_FSM_READY_BUSY since it then gives a prefetch error, which it wasn't before.

     

    Is there any way to get the source for the lib so I can further track down the issue?

     

    David

  • I also don't know if it matters (or how to fix it) but I'm getting a warning that section temp.out(flashAPI) was padded by 2 to a size of 2308
  • David, Just few thoughts: 1. Is the watchdog enabled? You need to service it in your erase loop if enabled. This may explain why it works when you debug-step! 2. Disabled all Interrupts? 3. There is an api callback routine Fapi_serviceWatchdogTimer() which is called during a read/verify/blank-check? operation, This routine and if you are calling any calls within this routine need to be running from RAM, although you are not using any flash read functions. Joe
  • Hi Joe,

     

    Thanks for the thoughts.

     

    1) I haven't enabled the watchdog.  I'm assuming it's disabled by default, but I couldn't find anything quickly scanning the documentation, I'll double check.

    2) I don't enable interrupts, but explicitly disabling them causes a prefetch abort whether I step over it or not.  When I remove the call to

    _disable_interrupt_() then I can step over the functions without a prefetch abort.

    3) All the flash api functions are running out of ram, I can see this from the disassembly view.

     

    Thanks,

    David

  • David

    Again these are just thoughts ;-)

    "2) I don't enable interrupts, but explicitly disabling them causes a prefetch abort"  may be a clue. That is a call to the halcogen's (sys_core) code and is probably residing in the bank you are operating on or in the erased section?

    Also verify the run location of Callback function to service watchdog timer which is used by the Blank, Read, and Verify functions whether WD enabled or not.

    And, Flush pipeline after erase/program operations using Fapi_flushPipeline().

    Joe

  • I appreciate the help.

    There is only one flash bank in the 1224 (plus bank 7 for FEE). So _disable_interrupt_() is in the bank that I am trying to erase/program. It is properly located within flash though (my bootloader takes sectors 0-6, I am trying to erase / program sectors 7-15. I know the flash API needs to run out of ram..but the entire bootloader doesn't need to, does it?

    I verified that Fapi_serviceWatchdogTimer() is in RAM (0x08003E38).

    Do I need to flush the pipeline after each call to Fapi_issueProgrammingCommand / Fapi_issueAsyncCommandWithAddress? Or only after they are all complete? I looked at the example bootloader and didn't the flush pipeline function called anywhere.

    Thanks,
    David
  • To add some more information (and confusion)

    In addition to the programming, which works when I step over Fapi_issueProgrammingCommand but not when I just let the program run, I am also trying to erase flash (sectors 7-15).

    If I step over the call to Fapi_issueAsyncCommandWithAddress, it will erase 2 sectors, and then I get a prefetch abort when I try to step over it for the third sector. However, if I assembly step into the command, it will successfully erase all of the sectors.

    I don't know what that means... I would think if it was just a timing issue that single stepping over would slow it down enough that it wouldn't be a problem, especially since it does 2 sectors OK.

    David
  • David,

    Flash API Ref guide says "The pipeline must be flushed before the first non-API Flash read after an operation that
    modifies the Flash contents (Erasing and Programming)." Now does that also mean fetching code from the same bank? I think yes.

    Just to verify, your wrapper function handleFlashWrite() is running from ram, right? Any code that gets executed while the FSM is NOT idle should be in RAM not the entire boot-loader.

    To be sure, call _disable_interrupt_() before you call handleFlashWrite().

    Good luck,
    Joe
  • Ok...I will add flushing the pipeline after writing / erasing...but since I don't past those function calls I don't think that is at least this issue.

    My wrapper function is running out of flash. Only the flash api functions are running out of ram, I'll look into running the wrapper functions from RAM, although I am not sure how to do that for a specific function.

    I will add disabling the interrupts.

    Thanks,
    David
  • It looks like the key way getting the wrapper function running from RAM.

    Of course now I have an undef entry when I try to use FEE afterwards...but I think I can figure that one out.

    Thanks for your help!
  • Hi David,

    You copied the flash related code to RAM and executed in RAM, it should be fine for flash API to access/erase/write to bank0 sectors (except for the sectors used by your code). I am wondering if it is caused by the new flash API library (2.1.1). I run my code using API 2.1.0 without any problem, and will try 2.1.1 later.

    Regards,
    QJ
  • Hi QJ,

    I saw the same behavior with both versions. I wasn't placing the functions that called the flash api functions in ram.. Once I placed the wrapper functions in ram it worked ok.

    David