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.

CCS/TMS570LC4357: Fapi EEPROM programing

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

Tool/software: Code Composer Studio

I am using the sample bootloader code provided by TI.

To test the functionality I am trying to validate that the EEPROM functions are correctly programming the EEPROM

I have a 32 byte test pattern I am trying to program into address 0x8000.

I am using the following utility:

oReturnCheck = Fapi_BlockProgram( 0, 0x8000, (unsigned long)&g_pulUpdateSuccess, g_ulUpdateBufferSize);

and have tested the following (seem to work correctly)

size = BLInternalFlashFirstSectorSizeGet();    returns 0x4000

size = BLInternalFlashSizeGet();    returns 0x400000

check = BLInternalFlashStartAddrCheck(0x8000, 32);     returns 0 - (its in Bank 0 which holds the bootloader and app)

I also tried the Fapi_doVerify() test which correctly identifies the failed programing and correctly provided the correct bad bytes.

 

The utility identifies that it is correctly processing the request without error, however the Code Composer memory view is showing that the EEPROM has not been modified.

 

Are there any other steps or utilities that have to be done to enable writing to the EEPROM (sorry, FLASH program memory)?



 

 

  • Hello John,

    The EEPROM is flash bank 7, please use 7 for the bank number:

    oReturnCheck = Fapi_BlockProgram( 7, 0x8000, (unsigned long)&g_pulUpdateSuccess, g_ulUpdateBufferSize);

    BLInternalFlashStartAddrCheck(..) is designed for checking the size of the program flash (bank0 and bank1).

  • Yes, found that info I should have said Flash...

    I am trying to program the code space in Bank 0 and 1.

    The example provided fails to program the Flash. All the other functionality seems to work correctly. I am using the "TMS570LC4357_UART_Boot" example.
  • Hi John,

    The example I posted in another post is only for reference. The example programs the application to Bank1 rather than Bank0. If you want to erase the sectors in Bank0, you need to copy the API related code to SRAM and execute those code from SRAM. Please refer to the bootloader on ti.com:

    1. change cmd file:

    MEMORY
    {
    VECTORS (X) : origin=0x00000000 length=0x00000020
    FLASH_API (RX) : origin=0x00000020 length=0x000014E0 //create a region for flash operation related objects
    FLASH0 (RX) : origin=0x00001500 length=0x002FEB00 //LS31x and RM48 Flash size is 0x300000
    SRAM (RW) : origin=0x08002000 length=0x0002D000
    STACK (RW) : origin=0x08000000 length=0x00002000
    }
    SECTIONS
    {
    .intvecs : {} > VECTORS

    /* Place the outputsection“flashAPI". It is composed of the input sections: */
    /* Fapi_UserDefinedFunctions.obj, bl_flash.obj, and F021_API_CortexR4_BE.lib */
    /* It has two different allocations. It allocated to FLASH_API for loading, and allocated to SRAM for running. */
    /* This output section is placed in the output file so that, when the program is loaded, */
    /* it is in the FLASH_API memory range. Sometime during system execution, before anything in flashAPI is used, */
    /* the application copies it from FLASH_API to SRAM. Note this copy is not done automatically. */
    /* I must be taken in the application code. Any other section that uses flashAPI (either calls its functions or */
    /* refers to its data) acts as if flashAPI is already in SRAM. The LOAD_START etc. statements establish symbols */
    /* that are used to implement the copy. The value of the symbol api_load is the starting load address. */
    /* Likewise, api_end has the ending load address, and api_run has the starting run address. */
    /* api_size is the size */
    flashAPI :
    {
    Fapi_UserDefinedFunctions.obj (.text)
    bl_flash.obj (.text)
    --library= ..\lib\F021_API_CortexR4_BE.lib (.text)
    } load = FLASH_API, run = SRAM, LOAD_START(api_load), LOAD_END(api_end), RUN_START(api_run), SIZE(api_size)

    .text > FLASH0
    .const > FLASH0
    .cinit > FLASH0
    .pinit > FLASH0
    .data > SRAM
    .bss > SRAM
    }

    2. add code to copy flashAPI section to SRAM:
    ;-------------------------------------------------------------------------------
    ;
    ; 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
  • My hope was to keep things simple by loading the bootloader into Bank 0 (0x8000) and the program into Bank 1 (0x200000) .

    The example did not change bank 1 either.
  • good, the example uses bank 1 for the application. It erases/programs the sectors in bank 1.

    If you want to erase the sectors in bank 1, and program your code to bank 1, you don't have to execute code from SRAM.

    But you code use 0x8000 as the starting address, it is located in bank 0.

    oReturnCheck = Fapi_BlockErase( 1, 0x200000, g_ulUpdateBufferSize); // will erase the whole sector
    oReturnCheck = Fapi_BlockProgram( 1, 0x200000, (unsigned long)&g_pulUpdateSuccess, g_ulUpdateBufferSize);
  • I did another test to see if I could program bank 1

    oReturnCheck = Fapi_BlockProgram( 1, 0x20000, (unsigned long)&g_pulUpdateSuccess, g_ulUpdateBufferSize);

    interesting result:

    source: 5A5A5A5A
    destination: 1A5A5A4A

    didn't seem to get the first byte correct..
  • The starting address for BANK 1 is 0x200000 rather than 0x20000.
  • Thanks QJ, this has been a tough one. (yes it was a typo).

    After some more effort last night I have been able re reliably create the 'bug' - here a test and the results:

    load application from scratch

    -> the CC brings up the break at main()

             -> the memory at 0x200000 is incorrect

    run the application from the break,

            -> look at the memory browser and the memory is correct - I have not executed the code to program the flash

    press key on UART to initiate the FLASH programming sequence

    the CC breaks before executing the code to program

          -> the memory browser has the old view of the correct code (auto updated)

    I manually refresh the memory browser from the brake point

          -> it shows incorrect code

    I step through the programming 

      ->  the memory browser shows incorrect values (even with manual refreshes)

    I let the code composer run (no break point)

        -> and refresh the memory browser - it shows correct values

    I pause CC

        -> the memory browser shows incorrect values

    I continue CC and refresh the memory browser

        ->  it shows correct values

    I pause CC

        -> the memory browser shows incorrect values

    I continue CC and refresh the memory browser

        ->  it shows correct values

    What are your thoughts?

  • Hello John,

    If the cache is enabled, the data in window browser is from the cache which may not be the same as in the memory. Please disable the cache, or use cache write-through property.
  • Where are these functions located in CC? I have no "Enable/Disable Cache Coloring" icon on my memory browser and "memory view preferences" presents GUI options? I'm using the XDS110 USB debug probe.

    I have tried another test. While running and showing the correct value in the memory browser, I read the address programmatically and compare it to good and bad values placing a break point if it sees the bad value without stepping in debug mode. Programmatically it is seeing the bad value even though the memory browser is showing the good value at the same time...

  • Hi John,

    The cache is enabled:
    _cacheEnable_();

    You can disable the cache by calling "_CacheDisable_(); "in main.c
  • 2502.halcogen FEE config.docxHere is the config from HALCoGEN. They are the default settings. Do you see any issues?

  • I put in _cacheDisable_(); as per your suggestion. 
     
    No change... still see the two different views.

    Do you see an issue with the HALCogen FEE configuration?

  • Here is the code I am using from the example


    uint32_t g_pulUpdateSuccess[] = {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777,0x88888888,0x99999999,0xAAAAAAAA,0xBBBBBBBB,0xCCCCCCCC,0xDDDDDDDD,0xEEEEEEEE,0xFFFFFFFF};
    uint32_t size;

    size = BLInternalFlashFirstSectorSizeGet();
    size = BLInternalFlashSizeGet();
    size = BLInternalFlashStartAddrCheck(0x200000, 64);
    uint16_t oReturnCheck;
    oReturnCheck = Fapi_BlockProgram( 1, 0x200000, (unsigned long)&g_pulUpdateSuccess, 64);

  • Hi John,

    You use F021 Flash APIs to erase and program the Bank 7 (EEPROM) and rather than the FEE drivers. If you want to use the Bank 7 to store data. I recommend you to use the FEE driver.

    The configuration for FEE in your doc looks good to me. The sample code for write data to FEE and read data from FEE:

    /* USER CODE BEGIN (0) */

    #include "ti_fee.h"

    /* USER CODE END */

    /* Include Files */

    #include "HL_sys_common.h"

    /* USER CODE BEGIN (1) */

    uint16 u16JobResult,Status;

    Std_ReturnType oResult=E_OK;

    unsigned char read_data[100]={0};

    uint8 SpecialRamBlock[100];

    unsigned char pattern;

    uint16 u16writecounter;

    unsigned int  FeeVirtualSectorNumber;

    unsigned char VsState, u8EEPIndex;

    unsigned char u8VirtualSector;

    uint8 Test_Recovery;

    uint8 Test_Cancel;

    void delay(void)

    {

    unsigned int dummycnt=0x0000FFU;

    do

    {

    dummycnt--;

    }

    while(dummycnt>0);

    }

    /* USER CODE END */

    /** @fn void main(void)

    *   @brief Application main function

    *   @note This function is empty by default.

    *

    *   This function is called after startup.

    *   The user can use this function to implement the application.

    */

    /* USER CODE BEGIN (2) */

    /* USER CODE END */

    void main(void)

    {

    /* USER CODE BEGIN (3) */

    unsigned int BlockNumber;

    unsigned int BlockOffset, Length;

    unsigned char *Read_Ptr=read_data;

    unsigned int loop;

    /* Initialize RAM array.*/

    for(loop=0;loop<100;loop++)SpecialRamBlock[loop] = loop;

    /* Initialize FEE. This will create Virtual sectors, initialize global variables etc.*/

    TI_Fee_Init();

    do

    {

    TI_Fee_MainFunction();

    delay();

    Status=TI_Fee_GetStatus(0 );

    }

    while(Status!= IDLE);

    /* Write the block into EEP Asynchronously. Block size is configured in ti_fee_cfg.c file. Default Block size is

      8 bytes */

    BlockNumber=0x1;

    TI_Fee_WriteAsync(BlockNumber, &SpecialRamBlock[0]);

    do

    {

    TI_Fee_MainFunction();

    delay();

    Status=TI_Fee_GetStatus(0);

    }

    while(Status!=IDLE);

    /* Write the block into EEP Synchronously. Write will not happen since data is same. */

    TI_Fee_WriteSync(BlockNumber, &SpecialRamBlock[0]);

    /* Read the block with unknown length */

    BlockOffset = 0;

    Length = 0xFFFF;

    oResult=TI_Fee_Read(BlockNumber,BlockOffset,Read_Ptr,Length);

    do

    {

    TI_Fee_MainFunction();

    delay();

    Status=TI_Fee_GetStatus(0);

    }

    while(Status!=IDLE);

    /* Invalidate a written block  */

    TI_Fee_InvalidateBlock(BlockNumber);

    do

    {

    TI_Fee_MainFunction();

    delay();

    Status=TI_Fee_GetStatus(0);

    }

    while(Status!=IDLE);

    /* Format bank 7 */

    TI_Fee_Format(0xA5A5A5A5U);

       while(1);

    /* USER CODE END */

    }

  • I am trying to write to the program memory in Bank 1 to program the Flash, not Bank 7 (see memory address 0x200000).

    Which interface is correct? Are 'blocks' the same as 'banks', and if not how do I translate between them?

    The programming also appears to be intermittent, some times it is successful, sometimes not.

    I can reliably generate a condition in which code composer provided two different views of memory.

    I understand something may not be configured correctly, but this is a CC bug and needs to be escalated.

    Other than the bootloader example code is there a simple few limes of code that we could both try and see if your hardware and mine are operating correctly?

  • Hello John,

    The diagrams in your doc show the FEE configuration. I thought you switched to FEE for storing data. In FEE driver, the block is a group of data.

    If you erase/program the Bank 0 and Bank 1, you need to use the F021 API but the FEE driver which is only used for bank 7 (used as an emulated eeprom).

    Your code looks good:

    uint32_t g_pulUpdateSuccess[] = {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777,0x88888888,0x99999999,0xAAAAAAAA,0xBBBBBBBB,0xCCCCCCCC,0xDDDDDDDD,0xEEEEEEEE,0xFFFFFFFF};

    uint32_t size;

    size = BLInternalFlashFirstSectorSizeGet();

    size = BLInternalFlashSizeGet();

    size = BLInternalFlashStartAddrCheck(0x200000, 64);

    uint16_t oReturnCheck;

    oReturnCheck = Fapi_BlockProgram( 1, 0x200000, (unsigned long)&g_pulUpdateSuccess, 64);

    But you need to erase the sector the sector first before your program the data to this sector.

  • I have added the erase and there are still errors in the programming.

    I have tried another Hercules TMS570LC43x board with the same results.

    Here is some information that may be helpful. I have a break point at the following line of code:

    Fapi_issueProgrammingCommand((uint32_t *) dst,( uint8_t *)src,(uint32_t) bytes,0,0,Fapi_DataOnly); //Fapi_AutoEccGeneration);

    As I am programming 64 bytes (32 each call) the line is executed twice. The first time the line is stepped over the Code Composer correctly moves to the next line of code. The second time the line is stepped over the Code Composer does  not return. If I press the 'pause' button the code is executing back at the key input loop. This can be reliably repeated.

  • Here are the results from the suggested lines of code.7382.Errors in flash step sequence.docx

  • John,

    I will write a simple project to program the data to flash using F021 API, and give you as a reference.
  • Hello John,

    Please use "Fapi_AutoEccGeneration" to replace "Fapi_DataOnly". Otherwise, there are ECC error for the data you programmed to flash. The ECC correction algorithm will correct the data when you read them. This is why you see the wrong data in CCS memory browser.
  • We are getting closer..

    I have modified Fapi_issueProgrammingCommand from:Fapi_DataOnly to: Fapi_AutoEccGeneration

    I also put test code in to do the following:

    - prior to a write to see if the value is correct at the location (@ 0x200000)

    - perform a write (@ 0x200000)

    - after the write test the value to see if its correct (@ 0x200000)

    - issue a second write at a different location (@ 0x200120)

    - test the original location again (@ 0x200000)

    Here are the results (stepping through the code one line at a time):

    The location was incorrect when first tested

    When the 1st erase/write was performed the Memory Rendering is now correct for all 64 locations (@ 0x200000)

    The 2nd erase/write was performed at the other location the Memory Rendering is correct at (0x200120) but now corrupted at (0x200000) - it was neither erased now cleared - just messed up

    I commented out the second erase and re-ran the code

    The memory was incorrect when entered, correct on the first write and stayed correct on the second write

    I commented out both Fapi_BlockErase requests - both memory at both locations remain correct

    Also the 2nd execution of  Fapi_issueProgrammingCommand no longer messes up the Code Composer step process..

    Looking closer, the 1st execution of the erase (targeting 0x200000) was corrupting the second location of memory (at 0x200120) even though the call was made to 0x200000...

    Here is the test code used:

       uint32_t *src;

       src = 0x200000;

       status = *src;

       if (status ==  0xea0004bd)

         src++;

       else

         src--;

       uint32_t Success[] = {0xea0004bd, 0x00000000,

       0x00000000, 0x00000000,

       0x00000000, 0x00000000,

       0x00000000, 0x00000000,

       0x4605b538, 0x2d06460c,

       0x2d08d005, 0x2d0ed003,

       0x2005bf18, 0x2010d108,

       0xfa34f000, 0x60044803};

       status = Fapi_BlockErase(1, 0x200000, 0x2000);

       status = Fapi_BlockProgram( 1, 0x200000, (unsigned long)&Success, 64);

                   src = 0x200000;

                   status = *src;

                   if (status ==  0xea0004bd)

                       src++;

                   else

                       src--;

       int16_t i;

       for (i=0;i<64;i++)

           pData[i] = 0xFFFFFFFF;

       uint16_t oReturnCheck;

       //oReturnCheck = Fapi_BlockErase( 1, 0x200120, 64);    <--- was corrupting 0x200000)

       oReturnCheck = Fapi_BlockProgram( 1, 0x200120, (unsigned long)&pData, 64);

                   src = 0x200000;

                   status = *src;

                   if (status ==  0xea0004bd)

                       src++;

                   else

                       src--;

  • Hello,

    Fapi_BlockErase( ..) is used for sectors erase. It can not erase portion of a sector.

    Fapi_BlockErase( 1, 0x200120, 64): 0x200120 is located in 1st sector of Bank 1, and 0x200120+64 is also in the sector 1, so only the 1st sector is ereased.

    If the size is 0x20000, 0x200120 + 0x20000 is in 2nd sector, so the 1st sector and 2nd sector will be erased.

    So before the 2nd write, you don't need to call Fapi_BlockErase(), otherwise the content of the 1st write will be erased.
  • What is the intended result of the block clear (as it relates to the cleared data pattern  - i.e. all 0's or 1's)?

  • Hi John,

    The content in the sectors will be erased, and all the data bit becomes 1. The data pattern should be 0xFFFFFFFF.

    For TMS570LC43x device, the ECC is enabled by default and cannot disabled. When you erase the flash, the ECC space is also erased, both become 0xFFFFFFFFF. When you read the content of the flash, there is ECC error, the data you read out is not 0xFFFFFFFFF. Some bits are changed since the ECC error correction.