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.

undef entry when using flash api

Other Parts Discussed in Thread: HALCOGEN, TMS570LS1224

Hi,

I am using flash api v 2.01 with the TMS570LS1224, CCS 6.1 and Halcogen 4.4.

 

I can successfully erase and write using the flash api with no optimization.  However, it seems that with full optimization (I haven't tried other levels yet) that the call to erase flash (Fapi_issueAsyncCommandWithAddress)  erases the flash, but then causes an undef entry before returning.

 

Are there any known issues with using optimization and the flash api?

 

Thanks,

David 

  • Hi David,

    Is this the same issue as you were having a while back? https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/409892/1472077#1472077

    I think the next step is still the same - to determine what is causing the UNDEF.   It's just going to be something like either executing an FPU instruction with the FPU turned off,

    or executing from a data area...

  • Hi Anthony,

    I don't know if they are the same issue or not. They both are seen when I use the Flash api, but I was able to work around the other issue by re-initializing the FEE module.

    I am seeing the issue in my bootloader code, which resides from 0x0000_0000 to 0x0001_FFFF. My main program starts at 0x0002_0000 with its int vectors.

    When I set a breakpoint in the bootloader code at the undef entry, the LR register showed address 0x0002_0010, which would indicate that it got an abort, tried to jump to the interrupt vector, and wasn't able to (which makes sense if the main flash area was erased) so it then generated an undef entry.

    So I was able to track that it is initially generating a prefetch abort. I'm not sure how to track this down further. The call that is causing it to fail is part of the flash api, so I can't step in to it to narrow it down any more.

    David
  • Hi David,

    Ok, so you have a Data Abort occurring in the flash API code.

    Then a secondary issue with your code at 0x0002 0000 where there is an undefined instruction in the vector table entry for Data Abort (0x0002 0010).

    Is that right?

    I guess there's two things you could do next. First (best answer I think) are to look at the Data Fault Status and Data Fault Address registers of CP15 to get information about the data abort. If it's a precise abort you can use the address register to figure out where it was.

    Also you could look at LR_abt - which is different than LR_und so the undefined exception wouldn't have overwritten it.
    This should hopefully get you close to the instruction that caused the abort. (if it's imprecise you may be a few instructions after the instruction that actually caused the problem...)


    Last - I think we actually went through this before but can't pull up the original thread - there's a function Fapi_setActiveFlashBank() that trips a lot of people up because even though it's documentation doesn't clearly indicated it, when you call this function it puts the flash bank in a state where you cannot read or execute from it...
    So if your abort vector comes from a seemingly 'good' flash location - you need to check if the flash was in a readable state when the abort occurred. If it wasn't readable - then what got executed may actually be junk.
  • Hi Anthony,

    I think the abort is a prefetch abort, not a data abort.  I can set a breakpoint on the prefect about entry in the interrupt vectors and it gets hit.

    The function that contains the flash api call that is causing the abort is run out of RAM, so I don't think it is an issue with trying to execute from flash when it isn't allowed.  This was initially an issue for me, but after running the entire function out of RAM (not just the flash API functions) it seemed to be OK.  

    I have put the function to erase flash below.

    Thanks,

    David

    #pragma CODE_SECTION(handleFlashPrepare, "flashAPI")
    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)
    			{
    
    				eraseIndex = startSector;
    				remaining = length;
    
    				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));
    
    
    				}
    			}
    		}
    	}
    
    	//We are required to flush the pipeline before anything else accesses flash
    	Fapi_flushPipeline();
    	TI_Fee_Init();
    
    	pRsp->status = flashEraseCheck((uint32_t)eraseStartAddrCheck, length);
    }

  • If I turn off optimization for the file this is in, my issue goes away. Is there a way to disable optimization for either just the call to Fapi_issueAsyncCommandWIthAddress, or for the whole handleFlashPrepare function.

    Is there any reason that optimization could be causing a problem, or is it probably just masking the real issue?
  • Hi Dan,

    I'm staring at the ARM TRM right now and the vector at 0x0000 0010 says Data Abort.

    When you set the breakpoint as described: "I think the abort is a prefetch abort, not a data abort. I can set a breakpoint on the prefect about entry in the interrupt vectors and it gets hit."

    Which address is the breakpoint set at? Prefetch would be 0x0000 000C.

    Also, what information are you getting out of the LR and CP15 when this happens? I think this is the thread we need to pull on.

    Do you have any other boards like a 3137 that you can reproduce the problem on ? The 3137 has an ETM port so we could use it to get a 'trace' of what is happening if you can reproduce the problem on it.

    EDIT:  I think the optimizer is interesting - but it changes so many things it's not a 'great' thread to pull on.   The exception could be a 2nd or 3rd order removed from what's changed by turning on the optimizer.     Why I'm focused on the LR / CP15 is that if we know who offended - it'll be a lot easier to explain the link to the optimizer and actually figure out how to fix the issue.   Its more of a guessing game to think from the optimizer change toward the problem's root cause.

  • The LR register shows 0x0000_0010, but the breakpoint that is hit is at 0x0000_000C

    I exported the contents of CP15, they are in the attached .txt file.

    I have a bootloader that is almost identical on the 0332 and we haven't seen an issue with it.  Then again, we hadn't seen an issue with previous versions of the bootloader on the 1224.

     

     

    6708.CP15.txt

  • Hi David,

    Sorry - my mistake. I forgot that the LR is +4 ahead of the address causing the exception. This seems to match the CP15 registers you sent showing a prefetch abort. So I'm now in agreement on the point of prefetch v.s. data abort.

    The IFSR & IFAR registers indicatie 'Precise Parity/ECC Error' at address 0x0000000C so I am guessing that this isn't the initial error, there must have been at least one prefetch abort before this error (otherwise, how would the code have reached the prefetch abort vector to get this fault...) AIFSR indicates that its on the ATCM which means the flash memory, and that it's uncorrectable.

    Since this fault is at the prefetch abort vector I'd wonder if you somehow erased ECC associated with the vector table - or if there was a jump back to flash before the flash was ready to read data correctly.
  • Hi Anthony,

    I don't think we have ECC enabled, and we don't do ECC generation on program load.. Would there still be ECC associated with the vector table? Since it is in our bootloader, the table is filled with branches to the corresponding location in the main application.

    Since it seems that the error is caused inside of the flash api function call, I would assume (hope?) that it is written in a way that wouldn't cause a problem, and this function never returns, so it is not executing code I wrote.

    Is there a way to get the source for the flash api in order to track it down further?

    I'm not sure how else to proceed further.

    David
  • You're right - you can see that internal ECC isn't enabled in the Auxiliary control register value. External ECC is enabled, but unless i'm reading the table wrong the value 0x409 is an internal abort. So things aren't adding up.

    I've got a 1224 launchpad - will your code run on this? We can get you access to the sources for the Flash API as well, but there's an agreement that needs to be put in place first.
  • I think the code will run on it but I'm not 100% sure...Normally it gets commands from a DSP, but I have modified it so that it just calls the function that is causing the abort.

    I can zip up the code and send it through a private message since it is proprietary. My company has an NDA in place with TI so I think we are good there.

    David
  • Ok, if you can strip out anything that needs an NDA that's even better.
    We'll give it a shot.
  • I tried sending you a private message...it got an error, so I tried to re-send it, but let me know if it didn't go through.

    Thanks,
    David
  • Hi David:

            I got the same problem when I start with TMP570LS1227, HAL 4.4.0, Hercules F021 API020101(F021_API_CortexR4_BE_NDS.lib) and KEIL 5.12, It looks like when execute the command Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, eraseStartAddr); it will generate a _prefetch error .

    In Disassembly mode, see below.

    after the Fapi_issueAsyncCommandWithAddress enterace address: 0x4858, when execute to 0x4870, the error occured ,or some times jumped to another undef loacation. I still don't know how to do with it.

    best regards.

    JinYu

  • Hi JinYu,

    The disassembly you are showing looks corrupted to me.
    I extracted the Async.WithAddress.obj from F021_API_CortexR4_BE_NDS.lib and disassembled it:

    000000:              Fapi_issueAsyncCommandWithAddress:
    000000:               .thumb
    000000:              .text:Fapi_issueAsyncCommandWithAddress:
    000000: B538             PUSH            {R3, R4, R5, LR}             ; This is missing in your disassembly
    000002: 4605             MOV             R5, R0
    000004: 460C             MOV             R4, R1
    000006: 2D06             CMP             R5, #6
    000008: D005             BEQ             0x00000016
    00000a: 2D08             CMP             R5, #8
    00000c: D003             BEQ             0x00000016
    00000e: 2D0E             CMP             R5, #14
    000010: BF18             IT              NE
    000012: 2005             MOVNE           R0, #5
    000014: D108             BNE             0x00000028 
    000016:              $C$L1:
    000016: 2010             MOVS            R0, #16
                                                                          ; this is where your PC is at in the screenshot
    000018: F7FFFFFE         BL              _Fapi_issueFsmCommand [0x18] ; This branch was disassembled incorrectly by IAR
    00001c: 4803             LDR             R0, $C$CON1 [0x2c]
    00001e: 6004             STR             R4, [R0]
    000020: 4628             MOV             R0, R5
    000022: F7FFFFFE         BL              _Fapi_issueFsmCommand [0x22] ; This branch was disassembled incorrectly by IAR
    000026: 2000             MOVS            R0, #0
    000028:              $C$L2:
    000028: BD38             POP             {R3, R4, R5, PC}
    00002a: 46C0             MOV             R8, R8                       ; This is a NOP to force alignment of the following data word
    00002c:              $d:
    00002c:              $C$CON1:
    00002c: FFF8            .half            0xFFF8
    00002e: 7110            .half            0x7110

    Please note the comments I embedded above.

    Summary:

    • Stack PUSH at the top of the function is missing
    • Two BL instructions were disassembled incorrectly by IAR:
      • F9FAF000 --> BL --> 0x4C66
      • F9F5F000 --> BL --> 0x4C66
    • Alignment of the Data Word at the bottom of the function is corrupted due to missing PUSH

    So there clearly went something wrong with our library and the way the IAR tool chain interprets it. For me it looks like IAR tried to inline this function and messed up something. So please disable auto inlining in IAR and see and tell us what happens.

    Best Regards,
    Christian

  • I looked at the disassembly in my project and it matches what Christian posted.

    What I have also found is that if I assembly step into the Fapi_issueAsyncCommandWithAddress command it seems to work OK, but if I just let it run I see the abort. I'm going to look into if there is a timing issue going on, which may also explain why I don't see the error with no optimization on and see it with optimization.

    I'm going to adjust the wait states in the FRDCNTL register to see if that has any affect.
  • David,

    Are you trying to execute the F021 Flash API and your related functions out of the Flash?
    The TMS570LS1224 has got only one flash bank and this won't work therefore.

    Best Regards,
    Christian
  • Hi Christian,

    No, the flash api functions, and the functions they are called from are run out of RAM.

    Our bootloader seemed to be working fine, and then we added some functionality and now see the prefetch error when we try to erase.

    Thanks,
    David
  • Hi David,

    Sorry I missed this from one of your early posts.

    In another post you wrote: "The LR register shows 0x0000_0010, but the breakpoint that is hit is at 0x0000_000C"

    0x0C is the Prefetch Abort

    If the PC is at 0x0C but the LR shows 0x10 this would mean that it points back to 0x0C, as the previous state is IA + 4 in ARM mode (ARM R4 TRM Section 2.8.1).
    This would mean, that the prefetch abort was generated by itself. Which makes kind of sense, as it is in Flash and you might not be able to access it.
    This makes also sense when we look at your CP15 extract:
    R Cp15_CP15_INSTRUCTION_FAULT_STATUS 0x0000000B 0x00000409 --> Precise Parity/ECC Error
    R Cp15_CP15_AUX_DATA_FAULT_STATUS 0x0000000B 0x00000000
    R Cp15_CP15_AUX_INSTRUCTION_FAULT_STATUS 0x0000000B 0x00400000 --> ATCM (Flash) is the source of the error
    R Cp15_CP15_DATA_FAULT_ADDRESS 0x0000000B 0x00000000
    R Cp15_CP15_INSTRUCTION_FAULT_ADDRESS 0x0000000B 0x0000000C --> 0x0C is the address
    But on the other hand it makes no sense if you added a breakpoint to 0x0C...
    So it is hard to debug this, if the source of the prefetch about isn't visible, btw. CP15 shows that there was no Data Abort.

    One more thing to check, did you enabled the CPUs MPU?
    If so then you have to make sure, that the TI OTP area is readable by the F021 Flash API.
    However, I don't think that this is a problem here, this would cause an abort much earlier during initialization of the Flash API.
    And there is no data abort indicated by CP15, so we can drop this.

    Best Regards,
    Christian
  • I don't believe we have the MPU enabled...how would I check?

     

    So I may be mis-reading it, or maybe it is an artifact of setting a breakpoint with optimization on.  But I set a breakpoint in the wrapper function that calls the flash API command.  The wrapper function *should* be run out of RAM.  When I turn optimization off, it looks like it is, but with optimization set to level 3 it looks like it is being run out of flash.  Am I not properly telling it to put the function in RAM?

    Function call:

    #pragma CODE_SECTION(handleFlashPrepare, "flashAPI")
    static void handleFlashPrepare(CmdFmt_Obj *pCmd, RspFmt_Obj *pRsp)

    Linker file:

    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
    
    }


    Function to copy flashAPI section to RAM:

        .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

    optimization off:

    optimization lvl 3:

  • It seems that having the functions declared static is causing the issue.  After removing the static keyword I don't see the error anymore.

     

     

  • Hi David,

    I think that static functions are more likely to be inlined, could it be that the function is inlined when using static and not after you removed the keyword?

    You can force the compiler to selectively not inline a function with the following two methods:

    1. #pragma FUNC_CANNOT_INLINE ( handleFlashPrepare )
    2. static void handleFlashPrepare(CmdFmt_Obj *pCmd, RspFmt_Obj *pRsp) __attribute__( (__noinline__) )

    From you last two screenshots it looks like the compiler performed heavy optimizations (-o3 on), which back up my inline assumption.

    One more tip, you could use copy tables instead of: LOAD_START(api_load), RUN_START(api_run), SIZE(api_size)

    8.8 Linker-Generated Copy Tables

    The linker supports extensions to the link command file syntax that enable the following:
    • Make it easier for you to copy objects from load-space to run-space at boot time
    • Make it easier for you to manage memory overlays at run time
    • Allow you to split GROUPs and output sections that have separate load and run addresses

    But this is up to you, it just that I prefer the copy tables as I think that they are easier to handle.

    Best Regards,
    Christian

  • Hi David,

    I found the following Errata Description in the CGT Defect History, which might be related to the issue you saw:

    -------------------------------------------------------------------------------
    FIXED SDSCM00050992
    -------------------------------------------------------------------------------

    Summary : The optimizer should not make a symbol an alias if it
    has either the location or code_section pragmas applied.

    Fixed in : 5.1.10
    Fixed in : 5.2.2
    Severity : S2 - Major
    Affected Component : Compiler Consultant (ci)

    Release Notes:
    For a reason external to the expression of the program, the user relies
    on function X being at a particular address A. The only method the user
    has to do this is to put the function in its own special subsection and
    place it at A in the linker command file.

    Workaround:
    Available workarounds are to:

    1. Reduce the optimization level to -o2.
    2. If using a COFF abi, you can move the functions into separate files.
    3. Add an __asm("NOP") to the function which will prevent an alias from
    being created.

    So can I be, that you used a Compiler prior to version 5.1.10 or 5.2.2?

    Best Regards,
    Christian
  • Hi Christian,

    Yes, you are correct. We are currently using compiler version 5.1.9. We have errors building when using later versions of the compiler. Using the pragma to force the function to not be inlined seems to work, although we do see sporadic issues....I will look into the work arounds you listed to see if any help.

    Thanks,
    David