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.

TMS320F280041: Flash API (version 1.56.01) on f280041 does not properly erase sectors

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

Hi All,

I am using flash api to update firmware over CAN on device using f280041 (it is a port of project on f28035).
And I ran into several issues with flashed data to be NOT correct and it seems that it comes down to the erase, because if I use uniflash to erase given sections, the data is correct.

The second problem problem is coupled to the fist one, and that is that both Fapi_doBlankCheck() and Fapi_doVerify() return success when clearly at least one of them should fail (if the contents of the flash are incorrect).

CPU is running from external crystal at frequency 100MHz, all "bootloader" code runs in RAM, so all further snippets are running from RAM.

I will include code snippets and describe situation:

First the initialisation:

static int flash_internal_init(struct net_dev *dev)
{
    int             ret     = 0;
    struct system * sys     = system_handle();
    int             clk_mhz = sys->clk.cpu.freq / 1000000; // sys->clk.cpu.freq holds CPU clock speed in Hz
    Fapi_StatusType f_api_status;

    EALLOW;
    // Increase wait states of flash for write/erase operations 
// (4 should be enough for 100MHz and external XTAL, but use 5 to be sure... Flash_setWaitstates(FLASH0CTRL_BASE, 5); f_api_status = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, clk_mhz); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_INIT); goto flash_init_exit; } f_api_status = Fapi_setActiveFlashBank(Fapi_FlashBank0); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_SELECT); goto flash_init_exit; } flash_init_exit: EDIS; return ret; }

Then the erase ...

const uint16_t SECT_COUNT = 32;
// Base of each flash sector
const uint32_t SECT_BASE[32] = {
    0x80000, 0x81000, 0x82000, 0x83000, 0x84000, 0x85000, 0x86000, 0x87000,
    0x88000, 0x89000, 0x8a000, 0x8b000, 0x8c000, 0x8d000, 0x8e000, 0x8f000,
    0x90000, 0x91000, 0x92000, 0x93000, 0x94000, 0x95000, 0x96000, 0x97000,
    0x98000, 0x99000, 0x9a000, 0x9b000, 0x9c000, 0x9d000, 0x9e000, 0x9f000,
};
const uint32_t SECT_LEN[32] = {
    0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000,
    0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000,
    0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000,
    0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000,
};
const uint32_t SECT_MASK[32] = {
    0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
    0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000,
    0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
    0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000,
};

static int flash_internal_erase(uint32_t sector)
{
    int                      i, ret = 0;
    Fapi_StatusType          f_api_status;
    Fapi_FlashStatusType     f_api_status_flash;
    Fapi_FlashStatusWordType f_api_flash_status_word;

    EALLOW;
    /* Walk through all sectors masked */
    for (i = 0; i < SECT_COUNT; ++i) {
        if (sector & SECT_MASK[i]) { /* We have match, erase */
            f_api_status =
                Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)SECT_BASE[i]);
            /* Wait for the fapi command */
            while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady) {
            }
            if (f_api_status != Fapi_Status_Success) {
                ret = -(FLASH_E_ERASE | f_api_status);
                goto flash_erase_exit;
            }

            f_api_status_flash = Fapi_getFsmStatus();
            if (f_api_status_flash != 0) {
                ret = -(FLASH_E_FSM_STATUS_ERASE | f_api_status_flash);
                goto flash_erase_exit;
            }
            f_api_status = Fapi_doBlankCheck((uint32_t *)(SECT_BASE[i]), B_8KSector_u32length,
                                             &f_api_flash_status_word);
            if (f_api_status != Fapi_Status_Success) {
                ret = -(FLASH_E_BLANK | f_api_status);
                goto flash_erase_exit;
            }
        }
    }
flash_erase_exit:
    EDIS;
    return ret;
}


and finally flash

#define FLASH_STRIDE 4

int flash_internal_write(struct net_dev *dev, struct net_buf *buf) { struct hal * hal = hal_inst(); struct system * sys = system_handle(); struct flash_buf * fls = (struct flash_buf *)buf->data; uint32_t * to_verify = (uint32_t *)fls->buf; uint16_t i; int ret = 0; Fapi_StatusType f_api_status; Fapi_FlashStatusType f_api_status_flash; Fapi_FlashStatusWordType f_api_flash_status_word; EALLOW; for (i = 0; i < fls->len; i += FLASH_STRIDE) { f_api_status = Fapi_issueProgrammingCommand((uint32_t *)(fls->addr + i), (fls->buf + i), FLASH_STRIDE, 0, 0, Fapi_AutoEccGeneration); while (Fapi_checkFsmForReady() == Fapi_Status_FsmBusy) ; if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_PROGRAM); goto flash_write_exit; } f_api_status_flash = Fapi_getFsmStatus(); if (f_api_status_flash != 0) { ret = -(FLASH_E_FSM_STATUS_WRITE | f_api_status_flash); goto flash_write_exit; } // Verify f_api_status = Fapi_doVerify((uint32_t *)(fls->addr + i), FLASH_STRIDE / 2, to_verify + (i / 2), &f_api_flash_status_word); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_VERIFY); goto flash_write_exit; } } flash_write_exit: EDIS; return ret; }

All the rest of the code is correctly working on f28035

EDIT:
Noteworthy thing is also that when the firmware is loaded by Flash API (regardless if successful or not) and I want to see the actual data in the flash and I do memory readback (actual readback OR verify of a hex file that I have loaded using my bootloader) in Uniflash I get this error: 

[ERROR] C28xx_CPU1: File Loader: Verification failed: Memory map prevented reading 0x88000@Program

or for readback:

Which seems to randomly appear on 88000, 89000 or 8a0000 start address... Which makes whole debugging more difficult..

Now the exact same happens now if I load the hex file using Uniflash (but the firmware boots which means that it successfully loads.

---


And it also happend if I ask flash api to erase sectors (Bank0 sector 3 through 10) all sectors before sector 8 read back 0xFFFF on all addresses, but sector 8 again shows ???? instead with error message about memory map preventing reading.

And this is only cured (i.e. I see 0xFFFF if I do erase of sectors 3 thorugh 10 using Uniflash instead... (after this bootloader also successfully loads firmware which makes sense a sector 8 is now correctly erased...)

In conclusion there are several questions to me..
Why does Flash API proceed programming if sector 8 would not be erased correctly?
Why does not blank check reveal that it was not erased?
And finally why is uniflash unable to read back? (it could be that the sector is really erased, but I cannot know without readback...)
Also why does it only happens on sectors 8 and higher?

  • Bruno,

    Please note that UniFlash uses the same Flash API as the low level driver for Flash operations.  

    Regarding the UniFlash read back issue: I think it is due to a gel file bug (Check the gel file provided at ti\uniflash_4.6.0\deskdb\content\TICloudAgent\win\ccs_base\emulation\gel\f280041.gel.

    In the function hotmenu F280041_Memory_Map(), you will notice that the Flash bank memory map is incorrect (as below).

       GEL_MapAddStr(0x00080000,1, 0x8000, "R|AS2",0);                      /*   FLASH BANK1 (64 KBytes)                                */

       GEL_MapAddStr(0x00090000,1, 0x8000, "R|AS2",0);                      /*   FLASH BANK2 (64 KBytes)                                */

    It should be:

       GEL_MapAddStr(0x00080000,1, 0x10000, "R|AS2",0);                      /*   FLASH BANK1 (128 KBytes)                                */

    I will file a ticket to fix this bug.

    I will get back to you on the Flash API debug.

    Thanks and regards,

    Vamsi

  • Thnak You Vamsi!
    Indeed this has fixed the readback problem... Now I can see that there is the "old" firmware data.. so the erase does not work for me for sector 8.. I'll try to limit the code on my side to just erase the bank 8 and see if I can create a minimal example that would run standalone...
  • Ok.. So I found out that I had an issue why my bootloader code would not issue erasing of anything over sector 8..
    This one is solved then and thigs are working. I get the firmware flashed through Fapi booting.

    There would be still one question though, actually two:
    1, Why does Fapi_issueProgrammingCommand() and it's company Fapi_getFsmStatus() does not fail on trying to write to non-erased flash (i.e. change 0 -> 1)
    2, Why does Fapi_doVerify() pass as success?
  • Bruno,

    Glad that I could help.

    #1. Fapi_issueProgrammingCommand() does not check whether the memory is already programmed or not.  But Flash wrapper logic will log the event in FMSTAT if you try to do a 0->1 by calling program function.  Are you sure that Fapi_getFsmStatus() is not reporting when you try to change a 0->1 via program operation? Do you have a test case to reproduce it? If yes, please send it to me.     

    This is mentioned in Flash API guide and wiki (http://processors.wiki.ti.com/index.php/C2000_Flash_FAQ).  Please search for "If the Fapi_issueProgrammingCommand() function does not wait for the program operation completion, how do we know whether the program operation succeeded or not?" in the Flash API wiki page.

    #2. Are you saying that verify function did not catch when the supplied data and target data are different?  Can you send me a test case to reproduce it? I can debug that and let you know.  

    Few more things to check:

    A) Did you program any DCSM settings in OTP to secure the device? I am wondering if that is causing the Flash to read back all 0s or something else is happening for you to think that Flash API functions are failing to catch it.

    B) F280041 has only one Flash bank. Why do you list all the bank 1 sectors in your code when there is only bank 0 in this device?

    C) I see that you initialized only the Flash wait states using Flash_SetWaitStates().  I would suggest you to use Flash_initModule() to initialize Flash module properly.  It is available at C:\ti\c2000\C2000Ware_1_00_06_00\driverlib\f28004x\driverlib\flash.c.

    Thanks and best regards,

    Vamsi

  • 1, Yes. I know that. And I check the return value  Fapi_getFsmStatus() and it is never anything elase than 0. I run this after each call to Fapi_issueProgrammingCommand.

            f_api_status_flash = Fapi_getFsmStatus();
            if (f_api_status_flash != 0) {
                ret = -(FLASH_E_FSM_STATUS_WRITE | f_api_status_flash);
                goto flash_write_exit; // This goes to handling code
            }


    If I just omit all erasing.. this does not generate an error... which I expect either return value of Fapi_getFsmStatus() to be != 0 or Fapi_doVerify() to be != Fapi_Status_Success.

    2, Ad 1. Experiment of omiting all erase code...
    I'll try to see wether I can produce a self-contained example. It is bit difficult because I have a HAL system for initialisation of HW and then the data to this flashing coce is provided by a Python application suplying data over CAN.. so I'll have to strip all of that out. 

    A: I check that flashing occures only in locations of flash in my hiher level code, so this should not happen.
    B: Idea is that it can be used on other f28004x devices and depending on the "hex" file these are used or not.. In this case since I have hex file linked for f280041 this are never used. 
    C: I have only used Flash_SetWaitStates() to change default value of 4 that I otherwise initialise flash with.. like so: Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES); The change to 5 is merely for case it the firmware would have been running on 100MHz using internal oscillator (I run from crystal), but I am trying to make it as permissive as possible, so therefore if the flash erase/write is used it is changed to 5.

    /// EDIT

    As promised I have produced a stand-alone example, and as expected when the second test_erase() is not called it ends up in error from Fapi_getFsmStatus() I'll see if that is error in my logic elsewhere or it's just an unsucessful attempt at reproducing the problem ...
    I am adding the reproduce code.. which does not reproduce but might be useful for others reading this thread..

    #define FLASH_STRIDE 4
    
    int test_erase(uint32_t sector)
    {
        Fapi_StatusType          f_api_status;
        Fapi_FlashStatusType     f_api_status_flash;
        Fapi_FlashStatusWordType f_api_flash_status_word;
        // First erase the sector
        f_api_status = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)sector);
        while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady) {
        }
    
        if (f_api_status != Fapi_Status_Success) {
            while (1)
                ;
        }
        f_api_status_flash = Fapi_getFsmStatus();
        if (f_api_status_flash != 0) {
            while (1)
                ;
        }
        f_api_status = Fapi_doBlankCheck((uint32_t *)sector, 0x800, &f_api_flash_status_word);
        if (f_api_status != Fapi_Status_Success) {
            while (1)
                ;
        }
        return 0;
    }
    
    int test_write(uint32_t sector, uint16_t *buf)
    {
        Fapi_StatusType          f_api_status;
        Fapi_FlashStatusType     f_api_status_flash;
        Fapi_FlashStatusWordType f_api_flash_status_word;
    
        uint32_t  i;
        uint32_t *buf32 = (uint32_t *)buf;
        for (i = 0; i < 0x1000; i += FLASH_STRIDE) {
            f_api_status = Fapi_issueProgrammingCommand((uint32_t *)(sector + i), (buf), FLASH_STRIDE,
                                                        0, 0, Fapi_AutoEccGeneration);
            while (Fapi_checkFsmForReady() == Fapi_Status_FsmBusy)
                ;
            if (f_api_status != Fapi_Status_Success) {
                while (1)
                    ;
            }
    
            f_api_status_flash = Fapi_getFsmStatus();
            if (f_api_status_flash != 0) {
                while (1)
                    ;
            }
    
            //Verify
    	    f_api_status = Fapi_doVerify((uint32_t *)(sector + i), FLASH_STRIDE / 2, buf32,
                                                &f_api_flash_status_word);
            if (f_api_status != Fapi_Status_Success) {
                while (1)
                    ;
            }
        }
        return 0;
    }
    
    void test_flashing()
    {
    #define TEST_SECTOR_BASE 0x88000
        // Write zeros
        uint16_t buf_zeros[FLASH_STRIDE]       = {0, 0, 0, 0};
        uint16_t buf_onetwothree[FLASH_STRIDE] = {1, 2, 3, 0xff};
    
        // First erase
        test_erase(TEST_SECTOR_BASE);
    
        // write zeros
        test_write(TEST_SECTOR_BASE, buf_zeros);
    
        // Second erase
        //test_erase(TEST_SECTOR_BASE);
    
        // write one two three
        test_write(TEST_SECTOR_BASE, buf_onetwothree);
    }

     

  • Ok.. So I have verified and I see why it was no reporting an error.. Now it's all resolved.
  • Bruno,

    Glad the issue got fixed.

    I am closing this post.

    Thanks and regards,
    Vamsi