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.

Compiler/TMS320F28075: Flash API works on initial run, but not after reset.

Part Number: TMS320F28075
Other Parts Discussed in Thread: C2000WARE, UNIFLASH

Tool/software: TI C/C++ Compiler

I'm stuck.

I'm trying to build a boot loader for the F28075.  The majority of my boot loader is pulled from the example program.

On initial load from the debugger, the API can erase and write flash without problem.  It can load and run the application after a reset.  But after any reset the Erase function (oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, SectorAddress);)  returns "Fapi_Status_Success" but then fails the blank check (and no flash was actually changed).  Since it can't get past this part, I can't tell if any writes would work after the reset.

Going through the forums here, I've checked that the API is running out RAM, which it seems to be (in this case RAMD0, if it makes a difference, though I've tried other sections).  And other sections of code that run out of RAM seem to be just fine according to the disassembly address.

CMD file:

GROUP
{
.TI.ramfunc
{ -l F021_API_F2837xD_FPU32.lib}

}
LOAD = BOOTLOADER,
RUN = RAMD0,
LOAD_START(_RamfuncLoadStart),
LOAD_SIZE(_RamfuncLoadSize),
LOAD_END(_RamfuncLoadEnd),
RUN_START(_RamfuncRunStart),
RUN_SIZE(_RamfuncRunSize),
RUN_END(_RamfuncRunEnd),
PAGE = 0, ALIGN(4)

******

First line of Main:

MemCopy(&RamfuncLoadStart, &RamfuncLoadEnd, &RamfuncRunStart);

******

Mem Copy function:


void MemCopy(volatile Uint16 *SourceAddr, volatile Uint16* SourceEndAddr,volatile Uint16* DestAddr)
{
while(SourceAddr < SourceEndAddr)
{
*DestAddr++ = *SourceAddr++;
}
return;
}

*******

Actual Erase Section Called function:

#pragma CODE_SECTION(Flash_Erase_Sector,"ramfuncs");
Fapi_StatusType Flash_Erase_Sector(Uint32 *SectorAddress, Uint16 SectorLength)
{
volatile Fapi_StatusType oReturnCheck;
Fapi_FlashStatusWordType oFlashStatusWord;

//
// Erase Sector:
//
EALLOW;
//oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, SectorAddress);
oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, SectorAddress);
//
// Wait until FSM is done with erase sector operation
//
while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
EDIS;


if(oReturnCheck != Fapi_Status_Success)
{
//
// Check Flash API documentation for possible errors
// If Erase command fails, use Fapi_getFsmStatus() function to get the
// FMSTAT register contents to see if any of the EV bit, ESUSP bit,
// CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
// more details)
//
Error((Uint16)oReturnCheck);
}
//
// Verify that Sector is erased. The Erase step itself does a
// verify as it goes. This verify is a 2nd verification that can be done.
//
EALLOW;
oReturnCheck = Fapi_doBlankCheck(SectorAddress, SectorLength, &oFlashStatusWord);
EDIS;
if(oReturnCheck != Fapi_Status_Success)
{
//
// Check Flash API documentation for possible errors
// If Erase command fails, use Fapi_getFsmStatus() function to get the
// FMSTAT register contents to see if any of the EV bit, ESUSP bit,
// CSTAT bit or VOLTSTAT bit is set (Refer to API documentation for
// more details)
//
Error((Uint16)oReturnCheck);
}

return oReturnCheck;
}

******************

Init function:


#pragma CODE_SECTION(Flash_Init_Flash_API,"ramfuncs");
void Flash_Init_Flash_API(void)
{
volatile Fapi_StatusType oReturnCheck;

EALLOW;
//Disable ECC
Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0x0;

//Initialize the Flash so that it can be written:
oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 120);

if(oReturnCheck != Fapi_Status_Success)
{
//
// Check Flash API documentation for possible errors
//
Error((Uint16)oReturnCheck);
}
EDIS;

Flash_Initialized = TRUE;
}

****

Note, before the erase sector functions are called, I turn off ECC, and turn off the watchdog.  The API init function is called when the boot loader starts up and before and communication can start.  The user functions are copied directly from the example without any edits.  

Any idea what I might be doing wrong.  This API is way more finicky than on the F28035 which is pretty simple to use.  I don't get how it only works on first load with the debugger then never again.

Thanks,

Kyle

  • Kyle,

    First time when you load, it might be passing since the Flash Plugin configured the Flash wrapper correctly.  Below are some things that you can check:

    1) I see .TI.ramfunc in your linker command file. But you are using "ramfuncs" in your code.  Did you map "ramfuncs" as well to Flash for load and RAM for run?  You may want to replace "ramfuncs" with '.TI.ramfunc" assuming that you are using the latest compiler.

    2) Did you call the Fapi_setActiveFlashBank(Fapi_FlashBank0)?

    3) Please use the memcpy() function instead of the memcopy() function.  memcpy() is part of RTS library now.

    4) Can you check the value of FMSTAT register after the erase operation? You can use Fapi_getFsmStatus() function for this. Details of FMSTAT register are provided in the description of this function in 3.2.7 Fapi_getFsmStatus() at http://www.ti.com/lit/pdf/spnu629.  Below is the sample code.

    // Erase the sector

    oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, SectorAddress);

    // Wait until FSM is done with erase sector operation
    while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}

    if(oReturnCheck != Fapi_Status_Success)
    {
         Example_Error(oReturnCheck);
    }

    // Read FMSTAT register contents to know the status of FSM after
    // erase command to see if there are any erase operation related errors
    oFlashStatus = Fapi_getFsmStatus();

    if(oFlashStatus != 0)
    {
         // Check Flash API documentation for FMSTAT and debug accordingly
         // Fapi_getFsmStatus() function gives the FMSTAT register contents.
         // Check to see if any of the EV bit, ESUSP bit, CSTAT bit or
         // VOLTSTAT bit is set (Refer to API documentation for more details).
         FMSTAT_Fail();
    }

    5) Did you check the address that the blank check function returned in poFlashStatusWord?  Is it the first address location of a sector?

    6) What is the Flash wait state configuration that you are using?

    7) Did you do a dummy read of the password locations as suggested in the CSM Password Match Flow (PMF) in TRM to unsecure the zone that you are trying to erase?

    8) Did you make sure that the PLL config is correct when the flash erase failed?

    9) Make sure to assign the functions in the Fapi_UserDefinedFunctions.c file to .TI.ramfunc if not already.  This should be already in place if you use this file from the C2000Ware.

    Flash API provided for this device is different than that of F28035 since the flash technology used is different.  Also note that the Flash in F2807x has more features like ECC, program more than one word etc. and hence it is a little complex than that earlier API.

    Thanks and regards,
    Vamsi

     

  • Thanks for the fast reply...

    1. Yes. There are two MemCopy functions that load to different sections of RAM.
    2. Yes, that is called once before the Erase Sector function and the result is checked before the first Erase Sector is called. It always fails on the first erase call.
    3. I tried it with this instead of the previous version with no luck (I'll leave it with the memcpy for now):
    New functions (showing both this time):
    memcpy(&RamfuncRunStart, &RamfuncLoadStart, (size_t)&RamfuncLoadSize);
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    4. Status comes back as 0xC10... According to the link, this is Erase Verify fail. I'm not sure if that helps pinpoint the problem...

    5. The first Value in the structure is 0x84000 which is the start of Sector C, which is the first sector I'm trying to erase.

    6. According to my InitFlash function, this is the setting:
    Flash0CtrlRegs.FRDCNTL.bit.RWAIT = 0x2; (This is also what register reads back after a erase fail). This looks to be proper for a 120MHz clock. Though it seems that if this setting was off, it wouldn't work at all, not just after programming.

    7. I wasn't because I didn't have a password set. I added it inside my flash init function (used the standard CsmUnlock found SysCtrl.c) . The same behavior exists, with the same Status of 0xC10 from the flash check function.

    8. I believe it is or my CAN timing (how I'm sending data) would be off and I wouldn't have communications.

    9. Like I said, I didn't adjust anything in that file, but I just checked and it's calling out to ".TI.ramfunc" as it did before.

    Let me know if you see what might be the issue.

    Thanks,
    Kyle
  • I thought I would clarify number 8. I have a 20MHz crystal on the processor and setup my PLL with the following:
    InitSysPll(XTAL_OSC,IMULT_12,FMULT_0,PLLCLK_BY_2); \\20MHz*12/2 = 120MHz

    I hope that helps.

    Thanks again,
    Kyle
  • Kyle,

    Not sure why you would use two different ramfuncs - any advantage? May be you allocate to two different RAM blocks - but how does it help? I am just trying to reduce the debug complexity here.

    Thanks and regards,
    Vamsi
  • Vamsi,
    Some of my code uses the old method of calling out "Ramfuns", versus the ".TI.ramfuncs" which seems to have been adopted after compiler version 6 was released.

    Why is needed? I have other functions that didn't fit into just one RAM block, so I split them. Up. In other programs certain programs need to run in faster memory (the 28035 had different RAM sections that ran at different speeds). If you are concerned that it won't because of this, then I wouldn't have much faith in your linker/compiler which should allow anyone to put whatever program they want wherever they want.

    I highly doubt this is what's causing the issue. But, I understand you are looking for anything.

    In playing around, I've noticed that adding CsmUnlock actually causes the erase to fail even just after the programming (where it previously did work).. This is leading me to believe that error is indeed caused by the processor locking those sections of memory. This would make sense that the debugger unlocks the memory and allows the Errase and write, then after reset it defaults to locked again.

    What doesn't make sense is why CsmUnlock, doesn't work:
    #pragma CODE_SECTION(CsmUnlock,"ramfuncs");
    Uint16 CsmUnlock()
    {
    //
    // Load the key registers with the current password. The 0xFFFF's are dummy
    // passwords. User should replace them with the correct password for the
    // DSP.
    //

    EALLOW;
    DcsmZ1Regs.Z1_CSMKEY0 = 0xFFFFFFFF;
    DcsmZ1Regs.Z1_CSMKEY1 = 0xFFFFFFFF;
    DcsmZ1Regs.Z1_CSMKEY2 = 0xFFFFFFFF;
    DcsmZ1Regs.Z1_CSMKEY3 = 0xFFFFFFFF;

    DcsmZ2Regs.Z2_CSMKEY0 = 0xFFFFFFFF;
    DcsmZ2Regs.Z2_CSMKEY1 = 0xFFFFFFFF;
    DcsmZ2Regs.Z2_CSMKEY2 = 0xFFFFFFFF;
    DcsmZ2Regs.Z2_CSMKEY3 = 0xFFFFFFFF;
    EDIS;

    return CSM_SUCCESS;
    }

    I confirmed that debugger is set to dummy passwords and that the processor is unlocked with UniFlash...

    There isn't much for the DCSM as far as examples go. The examples that call out DCSM don't even seem to deal with the DCSM at all. Am I missing something or can you point me to a better resource while I scour the DCSM section of the Techical Data Sheet.
  • Update on the CSmUnlock. Changing the Unlock function to (All flash keys set to 0xFFFF FFFF):

    #pragma CODE_SECTION(DcsmZ1Unlock,"ramfuncs");
    void DcsmZ1Unlock(void)
    {
    volatile long int *CSM = (volatile long int *)0x5F010; //CSM register file
    volatile long int *CSMPWL = (volatile long int *)0x78028; //CSM Password location (assuming default Zone sel block)
    volatile int tmp;
    int I;
    // Read the 128-bits of the CSM password locations (PWL)
    //
    for (I=0;I<4; I++) tmp = *CSMPWL++;
    // If the password locations (CSMPWL) are all = ones (0xFFFF),
    // then the zone will now be unsecure. If the password
    // is not all ones (0xFFFF), then the code below is required
    // to unsecure the CSM.

    // Write the 128-bit password to the CSMKEY registers
    // If this password matches that stored in the
    // CSLPWL then the CSM will become unsecure. If it does not
    // match, then the zone will remain secure.
    // An example password of:
    // 0x11112222333344445555666677778888 is used.
    *CSM++ = FLASH_KEY_0; // Register Z1_CSMKEY0 at 0x5F010
    *CSM++ = FLASH_KEY_1; // Register Z1_CSMKEY1 at 0x5F012
    *CSM++ = FLASH_KEY_2; // Register Z1_CSMKEY2 at 0x5F014
    *CSM++ = FLASH_KEY_3; // Register Z1_CSMKEY3 at 0x5F016
    }

    And:
    #pragma CODE_SECTION(DcsmZ2Unlock,"ramfuncs");
    void DcsmZ2Unlock(void)
    {
    volatile long int *CSM = (volatile long int *)0x5F050; //CSM register file
    volatile long int *CSMPWL = (volatile long int *)0x78228; //CSM Password location (assuming default Zone sel block)
    volatile int tmp;
    int I;
    // Read the 128-bits of the CSM password locations (PWL)
    //
    for (I=0;I<4; I++) tmp = *CSMPWL++;
    // If the password locations (CSMPWL) are all = ones (0xFFFF),
    // then the zone will now be unsecure. If the password
    // is not all ones (0xFFFF), then the code below is required
    // to unsecure the CSM.

    // Write the 128-bit password to the CSMKEY registers
    // If this password matches that stored in the
    // CSLPWL then the CSM will become unsecure. If it does not
    // match, then the zone will remain secure.
    // An example password of:
    // 0x11112222333344445555666677778888 is used.
    *CSM++ = FLASH_KEY_0;
    *CSM++ = FLASH_KEY_1;
    *CSM++ = FLASH_KEY_2;
    *CSM++ = FLASH_KEY_3;
    }

    I can now erase and write again, but not after reset. The register view on between the two is the same for DcsmZ1Regs between both modes... So unfortunately, I don't think this is the cause.

    I will try to migrate everything to ".TI.Ramfuns" and I'll let you know how that goes.

    Thanks,
    Kyle
  • Kyle,

    If you have not changed any of the security settings then CSM unlock should not cause any issue. In fact you don't need CSM Unlock function in this case. CSM unlock is only needed if user has changed the default password setting. What Vamsi was asking is security initialization which need to be done after reset. If using the debug reset then this is taken care by Gel file. If watchdog reset then BOOTROM takes care of the same. Which reset method you are using?

    Regards,
    Vivek Singh
  • Kyle,

    Vivek will take care of your security questions.

    Regarding the RAM usage: I got that you are trying to use different RAMs for speed reasons. But I don't think it is applicable for F28075 (or for F28035 - Vivek can confirm). Also, if something does not fit in a given RAM block, you can always club them in to single block in your linker command file.

    Thanks and regards,
    Vamsi
  • Vivek,

    My bootloader works on the first run, so when the debugger resets the processor everything works fine.

    I'm using the Watchdog to reset the processor via the functional code.  That's when I can't erase or write any longer, so this is where the BOOTROM is taking care of it.  This is where I need help.  As it just will not erase or write flash once the BOOTROM starts the processor.  The password has never been written, and the registers show that both zones are unsecure...

    What am I doing wrong?

    Thanks,

    Kyle

  • Kyle,

    Ist time after debug reset, do you load any code or run it via BOOTROM itself?
    Also after watchdog reset, do you know if your code is getting executed as expected? I mean does device boot properly after WD reset and jumps to your bootloader?

    Regards,

    Vivek Singh
  • Vivek,
    I run my own code. My own boot loader. I do not use, and I will not use TI's BOOTROM to write flash (it's not an option).

    Yes, my code is acting as expected. I have communication (CAN), I can read/write EEprom (separate IC using I2C). My LEDs are flashing properly. I setup and run PWMs for a power supply. I can even do a checksum on functional code somewhere else in the chip and then jump to it... The functional code runs just fine as well.

    The only thing I can't do after a reset is erase and write flash via my own boot loader (which works just fine after loading from a boot loader).

    I hope that helps.

    Thanks,
    Kyle
  • Guys,
    I got it to work.

    Something weird happens with the initialization or the initialization breaks for some reason and has to be redone. I'm not sure what or why. But it needs to get called again just before the erase function.

    So essentially, I fixed it by calling Fapi_initializeAPI again (although it's already called previously) in my erase function (previously I just had the setActiveBank in the erase. I'm not sure why this fixes the issue, but it does. For good measure I also included the CSMUnlock call here as well because I'll eventually need it.

    My erase function now essentially looks like this:
    CsmUnlock (Added)
    EALLOW
    Fapi_initializeAPI (Added, but called previously)
    Fapi_setActiveFlashBank
    EDIS

    Sector by sector erase and check functions.

    Also note.  In playing with the example.  I found that I couldn't run the example out of flash section A after a restart, and found that that to be the case with mine as well.

    So, I also blocked FLASH A from being used at all...  I'm not really sure why this is the case, but I don't need that memory anyway; so it's not a big deal.  

    Thanks for your help,

    Kyle

  • Kyle,

    Flash A has boot to Flash entry point.  That is why the application is not working for you after a restart when you erase it.

    Coming to the initialization:  When I inspected your code, I did not see the function call to Fapi_setActiveFlashBank(Fapi_FlashBank0) and hence asked you earlier to make sure it is in place.  May be you don't have EALLOW before calling it.  

    Thanks and regards,

    Vamsi

  • Vamsi,

    I appreciate that you guys have had quick responses.  But this last reply was not needed and just frustrates me more. 

    You just insinuated that I was running my program out of Flash A, then I erased Flash A and then  wondered why my program wouldn't run after a restart.   To me this is pretty insulting that I would do something so stupid.  Also,  It shows me that you guys apparently have no idea how a boot loader is supposed to function. 

    If you really think a boot loader erases itself then something is wrong with your understanding of a robust boot loader. NOTE:  A program can erase itself, but this is incredibly rare as it's dangerous to do an upgrade in the field as the potential to "brick" a device is very high.  A boot loader should be able to recover from a bad load or loss of power in the middle of an upgrade.  A program that erases itself can not do these things and therefore is not robust...

    This is after I told you, I can erase, write and load a program.  And that after I restart, it all still works, but your only API can no longer erase or write to flash.  I still have coms, I still have PWM functions, etc....  I've said this multiple times in this thread...  

    As for the setActiveFlashBank.  You directly asked me if I used that along with a bunch of other questions.  I replied about an hour later with where it was in my code and that I am definitely using it and also answering every other question as well. 

    So are you even reading my responses?

    On top of all of this.  Your API returns "success", when it failed  Your API error messages are not helpful at all.  In this case the API couldn't even tell me that it wasn't initialized properly anymore...

    Here is your outline to help that next stuck on this API:

    1.  Don't use Flash A, any other flash sector seems to be OK, but for some unknown reason it will not work properly, so just mark it as unusable for practical purposes.

    Don't believe me on this?  Try it with your example code.  Load it out of Flash A (not D) and add a restart... it will stop functioning... but it will restart and run the program, just the API will fail.

    2.  Your erase function should look generally like this:

    EALLOW;

    CsmUnlock();  //If needed

    Fapi_Init Function();

    Fapi_setActiveBank();

    Erase Sectors you want to erase...

    EDIS;

    3.  Then you should be good to write just like the example.

    I apologize for being harsh, but this was way more frustrating than it needed to be and you topped it off by insinuating that I had no clue what I was doing.  It showed you really weren't reading what I was replying.

  • Kyle, 

    I regret that my post came across as insulting.  It was not my intention.  I strive to provide the best support possible for our customers.  However, electronic communication sometimes has its limitations.  I agree sometimes my questions are basic for advanced users.  My intention is only to help narrow down the problem. 

    I would like to step through each item you have reported to date to make sure I understand and to address your questions: 

    1) Fapi_issueAsyncCommandWithAddress() returns success:    

    This function issues the command and returns.  It does not wait for the result so that the CPU can continue with other related tasks.  Please refer to section 3.2.2 in API guide (http://www.ti.com/lit/spnu629) for information on checking the erase status using Fapi_getFsmStatus() and Fapi_doBlankCheck().   

    2) Fapi_initializeAPI() returns success:  

    This function initializes the API and not the hardware registers.  This function will not fail to initialize if the RAM used by the variables of this function is not secured (if it is secured, it should belong to the same zone as that of the memory from which API is executing).  

    3) Regarding the Flash A sector usage problem:  

    After reviewing your description, I replaced Flash D with Flash A in the Flash API example’s linker command file.  I executed the example and then did a debug reset/restart sequence and it worked fine.  I also tried doing a power cycle followed by a debug restart, and it worked fine.  Not sure if I am missing anything else to match your procedure.  Please let me know and I can repeat the experiment.  

    4) Boot Loader:  

    On Nov 27th, you mentioned you are doing “Sector by sector erase and check functions” – which led me to think that you might have erased Sector A.  As part of my normal debug process I wanted to confirm that the entry point was still programmed.   If your application starts, and the comms and peripherals are working, then I agree this is not the case. 

    5) Fapi_initializeAPI() being called twice: 

    This is not required.  I understand it seems to resolve the issue but it should not have been required – I think there is still a problem in the code.   

    Here are some debug ideas:

    • Is it possible the application has overwriting the RAM used by the initialization after the first call?  This would have the impact of corrupting the initializations required for later API calls.
    • Is the code sequence before and after the reset different?  Is it possible the Flash API initialization is not done after the reset? 
    • This function must be called if the system frequency or wait-states are changed (section 3.1.1 in the API guide).  In your case, did any of these change between the first and the second calls to Fapi_initializeAPI()?  

    On Nov 27th, you said you had only Fapi_setActiveFlashBank() initially in the erase function.  I checked your erase function and initialization function that you posted on Nov 20th.  I saw Fapi_initializeAPI() in your initialization function, but I did not see Fapi_setActiveFlashBank() in the erase function.  I thought that you might not have noticed the missing Fapi_setActiveFlashBank() in the erase function.  I thought you might have added both Fapi_initializeAPI() and Fapi_setActiveFlashBank() functions along with EALLOW in erase function later while debugging leading to success.  But looks like you have another erase function (which you are calling as erase function) which calls the “Flash_Erase_Sector” function.  I thought Flash_Erase_Sector() as the erase function that you are referring to and provided inputs based on that assumption.  Let me know if I am missing anything.

    Thanks and regards,

    Vamsi