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.

Hercules RM48L952ZWT Flash Erase Does not Work Using FAPI API

Other Parts Discussed in Thread: RM48L952, HALCOGEN

Hi. We are using the TI Hercules RM48L952ZWT board and the example bootloader on Bank0 the 1st 4 sectors. The bootloader works jumping to our application that starts later on bank 0 (address 0x00020000. The problem is when we have a new application, and we want the bootloader to erase flash sectors of our application in the later sectors of Bank 0 and Bank 1, before trying to of course program the new application binary. The FAPI functions (version 02.01.00) are not erasing the flash. Below is some test code. and have verified in CCS memory browser that Flash is not erased (as well as Fapi_doBlankCheck the fails) Are we missing a step?  Thank you.

Fapi_StatusType bootloader_FlashApplicationRegion(void)

{

Fapi_StatusType FapiStatus = Fapi_Error_Fail;

uint32_t flashAddress = 0x00020000;

Fapi_FlashStatusWordType oFlashStatusWord;

uint32_t Freq_In_MHz;

Freq_In_MHz = SYS_CLK_FREQ; //=160

Fapi_initializeAPI((Fapi_FmcRegistersType *)F021_CPU0_REGISTER_ADDRESS, Freq_In_MHz);

FapiStatus = Fapi_setActiveFlashBank(Fapi_FlashBank0);

if ( FapiStatus == Fapi_Status_Success )

{

   while (flashAddress <= 0x002E0000 )

    {

      FapiStatus = bootloader_FlashEraseSector(flashAddress);

     if (FapiStatus == Fapi_Status_Success)

     {

         /* Verify that needed space was erased properly */

        FapiStatus = Fapi_doBlankCheck( (uint32_t *)(&flashAddress), 0x7FFF, &oFlashStatusWord);

        if (FapiStatus != Fapi_Status_Success)

         {

             UARTprintf("\r\nERROR: Fapi_doBlankCheck ...... \r\n");

             break;

        }

       flashAddress = flashAddress + 0x00020000;

       if (flashAddress == 0x00180000)

        {

              FapiStatus = Fapi_setActiveFlashBank(Fapi_FlashBank1);

            if ( FapiStatus != Fapi_Status_Success )

             {

                UARTprintf("\r\nERROR: Fapi_setActiveFlashBank Fapi_FlashBank1...... \r\n");

                break;

              }

         }

       }

      else

      {

        UARTprintf("\r\nERROR: bootloader_FlashEraseSector ...... \r\n");

       }

    }

  }

   else

  {

   UARTprintf("ERROR: Fapi_setActiveFlashBank-Fapi_FlashBank0 ...... \r\n");

  }

   return (FapiStatus);

}

Fapi_StatusType bootloader_FlashEraseSector(uint32_t ui32Address)

{

  Fapi_StatusType FapiStatus = Fapi_Error_Fail;

   FapiStatus = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t*)(ui32Address));

   if ( FapiStatus == Fapi_Status_Success )

  {

   /* Wait till sector erase command has finished */

    while ( Fapi_checkFsmForReady() == Fapi_Status_FsmBusy );

   /* Check for errors during sector erase */

    if ( 0ul == Fapi_getFsmStatus() )

    {

      FapiStatus = Fapi_Status_Success;

    }

  }

   return (FapiStatus);

}

  • Hi Jean-Marc. Thank you.

    You recommended:

    1. "The quick way to fix this problem is to edit the property of system.c and specify no optimization. The rest of the project will still have optimization"

    Is there a special register that controls this, or where/how in system.c can we specify no optimization? I can look up in datasheet if I can just have a register name.

    2. On 2nd change I understand. I had left it at the value of the default, so I will change this. At some point we will scale it down (because we do not need the default UART functionality), but better to assume for now it is growing until it works.

    Thank you again.
  • Tammy,

    In CCS, expand your project to display the source code.
    Right click on system.c and select Show Build Setting.
    From there, select CCS Build-> ARM Options->Optimization and set Optimization level to off and Speed versus size to none.

    As I said, this will only affect system.c all other files will be compiled with the properties set at the project level.

  • Hi Jean-Marc (and Anthony). Thank you. I have implemented the 2 changes.

    The good news is Fapi_InitializeBanks now returns Fapi_Status_Success. But now running the next F021 library function Fapi_issueAsyncCommandWithAddress , specifically

    Fapi_issueAsyncCommandWithAddress (Fapi_EraseSector, (uint32_t*)(ui32Address)); where ui32Address = 0x20000;

    results in an unrecoverable exception (the bootloader us stuck in an endless loop in sys_intvecs.asm c #0x1FFF8 ; 0x04 line 36).

    What do you think?

    Thank You Again.
  • Tammy,

    JM has your code working here - he just showed it to me. Not sure what's causing the abort in your instance but might be good to get his latest copy of the project and try it.
  • Hi Anthony. Ok can you ask him to zip the project it and upload it? Thank you again.
  • Tammy,

    Here is the zipped folder: 7103.SafetyMCU_Bootloader_Original_FlashIssue.zip

    In SafetyMCU_Bootloader_Original_FlashIssue\SafetyMCU_Bootloader_Original\RM48\boot_uart I've renamed the CCS project to:

    "boot_uart_RM48_Tammy"

    That way you can import it in the same workspace as your actual project.

    I did another modification that should be irrelevant for the problem you are seeing in system.c
    In void setupPLL(void) I've added the following code:

        /* Disable PLL1 and PLL2 */
        systemREG1->CSDISSET = 0x00000002U | 0x00000040U;
        /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */
        while((systemREG1->CSDIS & 0x42U) != 0x42U)
        {
        /* Wait */
        }

        /* Clear Global Status Register */
        systemREG1->GBLSTAT = 0x301U;

    This is the way the latest Halcogen code is generated. The rational is, before changing the PLL setup, it is recommended to disable the PLL first.
    That was not done in the Halcogen release used when the bootloader was developed.

    As summary, in bl_main.c on line 76 I've changed:

    uint32_t g_ulUpdateStatusAddr = 0x0FFC0;             //was 0x07FC0

    The compilation optimization for system.c are off.

  • Hi Jean-Marc. Thank you. I downloaded and imported this project and still have that same problem as above. In the memory browser it erases flash, but it does not exit the Fapi_issueAsyncCommandWithAddress() function and loops in that exception code in sys_intvecs.asm (and I gave it about 30 seconds of waiting).   How long should it take? Did you select option #3 on the test menu or tried erasing the Flash with a different menu option and Fapi function?

  • Hi Jean-Marc. Something strange. when I have no breakpoint and just run, the behavior is as above (goes into an exception) and never exits the function. But when I put a breakpoint at the Fapi_issueAsyncCommandWithAddress() and singlestep with the debugger the disassembly -- it will execute the code Ok and exit the function.
  • Tammy,

    FYI - CCS has an option - and defaults to - disabling interrupts when stepping. So if your code behaves differently during stepping then one thing to check is whether an interupt occurs during the 'run' causing the undef exception.
  • Tammy,

    You can only set breakpoint in the Flash code after you reach main. Remember the code is in Ram only after it has been copied to Ram. I will have a look tomorrow.

  • Hi Jean-Marc. Thank you. When the debugger starts up, it starts at the main function in bl_main.c. I set the breakpoint in sd_card.c the Fapi_StatusType bootloader_FlashEraseSector(uint32_t ui32Address) function. line 1073

    FapiStatus = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t*)(ui32Address));

    with no breakpoint the system is infinitely looping around the syst_intvecs.asm line 36

    b #0x1FFF8 ;0x04

    With the breakpoint FapiStatus = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t*)(ui32Address));
    and I singlestep through the disassembly of the FAPI function (it is part of the F021 lib so we do not have source), and it completes the function and exits ok without the problem of the infinite looping around the exception.

    I will disable all interrupts and see if the problem goes away. But Is that necessary to disable interrupts in order to use the F021 Flash libraries?

    Thank you again and I will wait to hear from you.
  • Tammy,

    Sorry for the misunderstanding, but I was using the option 1 and not 3.

    So when using 3, I realize that the binary filename is hard-coded. So I've copied a binary file on the SD Card with following name:

    newb.bin

    The code was failing opening this file and I had to change the following line:

    from: char newFileName[9] = "/newb.bin";
    to       char newFileName[9] = "newb.bin";

    Than I was able to see the problem you are experiencing.
    In sd_card.c, there are 2 function that have to be executed from RAM:

    bootloader_FlashApplicationRegion and bootloader_FlashEraseSector

    It is not possible to copy the full sd_card.obj in RAM (not enough space) so here is the trick.
    Via the linker command file, you can specify where a section is mapped as following:

       flashAPI :
       {
         ..\Debug\Fapi_UserDefinedFunctions.obj (.text)
         ..\Debug\bl_flash.obj (.text)
     This will map all the code section (.text) from UserDefinedFunctions.c and bl_flash.c in the section flash_API.

    In order to map only a specific function to a section, it is necessary to assign the function to a section name.
    In the compiler option-> Advance Options there is a switch (On/Off) name: "Place each function in a separate subsection" The default is Off.
    So for the file sd_card.c change it to On.

    Now, in a similar way the following syntax can be used in the linker command file:

         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashApplicationRegion)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseSector)

    This will force the linker to link these 2 functions part of sd_card.obj in the flashAPI so at run time this section can be copied in RAM.

    In your implementation, you are using more Flash_API than the original bootloader was. I've found Fapi_doBlankCheck.
    This is the same, this function has to be in the flashAPI section to be executed from RAM.

    In the linker command file, the following line has to be added:

                                         Read.Fapi_doBlankCheck.obj

    If other Flash API are used, they will have to be listed as well in the linker command file.
    To make room in RAM to fit all these new routine, I had to remove the following code:

    //     ..\Debug\bl_flash.obj (.text)

    That means the option 1 (Download via UART) does not work anymore.

    After all these modification, I was able to execute your code further, but is is falling after the Fapi_doBlankCheck. It is certainly an argument problem, size or other. I think you have all element in hands to continue the debug on your own.

    Please let me know if these explanation were useful.

    Here is the full flashAPI definition in the linker command file:

       flashAPI :
       {
         ..\Debug\Fapi_UserDefinedFunctions.obj (.text)
    //     ..\Debug\bl_flash.obj (.text)
         ..\Debug\bl_sdcard.obj (.text)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashApplicationRegion)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseSector)
         --library= F021_API_CortexR4_LE.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.Fapi_doBlankCheck.obj
                                              Read.MarginByByte.obj
                                              Read.Common.obj
                                              Read.FlushPipeline.obj
                                               Read.WdService.obj
                                              Async.WithAddress.obj
                                              Program.obj > (.text)
       } load = FLASH_API, run = SRAM, LOAD_START(api_load), RUN_START(api_run), SIZE(api_size)
    In BOLD are the modification I've made.

  • Hi Jean-Marc. Thank you . I changed the bl_link.cmd file as recommended above to:

    flashAPI :
    {
    ..\Debug\Fapi_UserDefinedFunctions.obj (.text)
    //..\Debug\bl_flash.obj (.text)
    ..\Debug\bl_sdcard.obj (.text)
    ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashApplicationRegion)
    ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseSector)


    --library= F021_API_CortexR4_LE.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.Fapi_doBlankCheck.obj
    Read.MarginByByte.obj
    Read.Common.obj
    Read.FlushPipeline.obj
    Read.WdService.obj
    Async.WithAddress.obj
    Program.obj > (.text)
    } load = FLASH_API, run = SRAM, LOAD_START(api_load), RUN_START(api_run), SIZE(api_size)

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

    The warning I get is

    <Linking>
    "../bl_link.cmd", line 21: warning #10068-D: no matching section


    which is the line 21 is

    ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseSector)



    Thank you again.
  • Tammy,

    Did you modified the compile option for the auto section name?

    Also check that this function is in sd_card.c

    If not do the same for the file that contains this function.

  • Tammy,


    I did check on my setup about the bootloader_FlashEraseSector warning during link time.

    In my case, to be able to debug the code easier, I've removed all optimization. In this configuration the linker does not complain about the section.

    Apparently when the code is optimized, this routine seems to be embedded and does not show up in the map file. I did check at run time and this code is executed.

    So to summarize, if I don't use optimization on the project, the linker does not complain about this section.
    With optimization, these is a warning at link time on the specific section, but the code executes correctly.

  • Hi Jean-Marc. Thank you. Yes I removed all the optimizations on the other files as well, and the warning is gone. After the erase flash is complete, and we are ready to program the flash .bin file on the sdcard (using the simple file system io API that you say I integrated).  With the limitations of our size of RAM you mentioned. What is the best way than to program the binary file into flash? can we just use standard fio functions and just limit the size of the buffer?

    i.e., psuedocode

    ...

    bank_number = 0;

    FlashDestination = 0x00020000

    fname = &newFileName[0];

    iFResult = f_open(&fname, buf, FA_READ);

    while (not end of file)

    {

    //

    // Enter a loop to repeatedly read data from the file and display it, until

    // the end of the file is reached.

    //

    do

    {

        //

        // Read a block of data from the file. Read as much as can fit in the

       // temporary buffer

        //

        iFResult = f_read(&fname, buf, sizeof(buf)  (UINT *)&ui32BytesRead);

       //

       // track size of the last chunk of the file that was received.

       //

       g_Size = g_Size + sizeof(buf);

       //

       // If there was an error reading

       //

       if(iFResult != FR_OK)

      {

       UARTprintf("Problem reading file \r\n");

       g_Size = 0;

      break;

      }

     

        oReturnCheck = Fapi_BlockProgram( bank_number, FlashDestination, (unsigned long)buf, buf_size);

        FlashDestination = FlashDestination + buf_size;

        if (Flash_Destination >= 0x00180000)

        {

           bank_number = 1;

        }

    }

    while(ui32BytesRead == sizeof(buf) - 1);

    ....

     

    Thank You Again.

     

  • Tammy,

    This is the way to go.
    Yes you can read the binary file to a buffer and program it to flash. This is the way it is done with the UART version.
    We receive block of data (check for integrity, this is not necessary when reading from SD card) and program to flash.
    You have to keep track of your destination address in flash to switch from Bank0 to Bank1 whenever necessary.

    If your final application need ECC, than there is an option (Fapi_AutoEccGeneration) to program the main flash with the data and automatically calculate the corresponding ECC. This calculation is done by the Flash Wrapper itself (Hardware).

  • Hi Jean-Marc.  Thank you. I have uploaded the project with your suggested changes here:1881.SafetyMCU_Bootloader_Original_FlashIssue.zip

    The good news is I got farther (flash erases Ok, and it then tries to program. The bad news is after just after programming to flash a few bytes using the Fapi_BlockProgram( programFlashBankNumber, programFlashDestination, (unsigned long) buf, ui32BytesRead);   which calls the Fapi_issueProgrammingCommand function. In this function is where it goes into this endless loop around the exception again (what used to happen in the erase).

    see bl_flash.c . line 273 :

    Fapi_issueProgrammingCommand((uint32_t *)dst,

    (uint8_t *)src,

    (uint32_t) bytes,

    0,

    0,

    Fapi_AutoEccGeneration);

    as is done with the UART version. I get the same wierd result of looping in sys_intvecs.asm.  

    See below memory browser: a few bytes are programmed before it dies in ths endless loop. I updated bl_link.cmd as I did with the erase but the problem still happens:

  • Tammy,


    You are facing the same exact problem.

    Fapi_BlockProgram has to be located in RAM.
    Yes you correctly modified the linker command file with:

         ..\Debug\bl_flash.obj (.text:Fapi_BlockProgram)

    but you forgot to specify for bl_flash.c the advance runtime compile option to generate a section name for each function.

    I did it and faced a size problem when the linker is trying to map all this code in RAM.
    By chance I found another mistake, (I forgot to tell you that this morning) In the linker command file, the following line is not necessary:

    //     ..\Debug\bl_sdcard.obj (.text)


    We don't need the full sdcard.obj to be located in RAM, only some function listed as:

         ..\Debug\Biolase\source\sd_card.obj (.text:sdCardCatFlash)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashProgramApplication)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashApplicationRegion)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseApplication)
         ..\Debug\Biolase\source\sd_card.obj (.text:bootloader_FlashEraseSector)

    So after these modification, I was able to program the first buffer. But your code exits from the

    do
    {

    }      while(ui32BytesRead == sizeof(g_pcTmpBuf) - 1);

  • Hi Jean-Marc. It works now. Thank you. The .out file builds to 367 KB. If each sector is 0x7FFF in size (32K), is the .out file reflective of how many sectors are needed on the Flash part for the bootloader? Or how is the calculation done? When I clean it up, do you still want a final copy for the TI library of bootloader examples? What is the cleanest way to change the name of the project? Just edit the name in CCS and manually edit and replace the project name in the project files?
  • Tammy,

    The only way I know to change a project name is to edit in the root directory of your project the following file:

    .project

    I usually copy the full project in a different directory then I edit .project

    In .project, search for:
    <projectDescription>
        <name>boot_uart_RM48_Tammy1</name>

    boot_uart_RM48_Tammy1 is the name of the project as visible in your workspace. This name has to be unique in a given workspace.

    Once you change it to let say boot_uart_RM48_Tammy2, save.

    The project name does not have to match the project root directory name.

    Concerning the size of the bin file, there is no information about sector size. So you have to read the bin file buffer after buffer.
    When you execute iFResult = f_read(&g_sFileObject, g_pcTmpBuf, sizeof(g_pcTmpBuf),(UINT *)&ui32BytesRead);
    ui32BytesRead contains the number of bytes read from file. It is normally sizeof(g_pcTmpBuf) but for the last read.

  • I know this is an older post, but I am working through similar issues with the 3137 boot loader. The boot loader code (especially the flash functions) is garbage. Do not trust any of it unless you unit test for your application. Lots and lots of programming mistakes are hidden in this code.

    A trivial unit test uncovers a bunch of mistakes, once you can get this to run you can continue.
    1) Fapi_enableMainBankSectors() mask of 0xFFFE is ok for bank0 protecting loader but same mask is not appropriate for bank1. First sector of bank 1 will NOT erase with this code. Hangs at FAPI_GET_FSM_STATUS.
    2) (NUMBEROFSECTOR-1) is wrong.
    3) No handling for out of range Erase_Start_Address. It will try to erase sector 0!!!

    I have no confidence that the TI BL code will work correctly for multiple sectors, blocks spanning sectors, blocks spanning banks, etc...

    Something simple like the following will catch the most basic problems (masks).

    bool test_flash(void)
    {
    bool flash_ok = false;

    uint8_t i;
    /*
    * Verify erasing one sector at a time. (Skip the sector 0, we are running from.)
    */
    for (i=1U; i<NUMBEROFSECTORS; i++)
    {
    if (0UL == Fapi_BlockErase(flash_sector[i].start, flash_sector[i].length))
    {
    debug_write_string("OK.\r\n");
    }else{
    debug_write_string("block_erase failed.\r\n");
    break;
    }
    }

    return(flash_ok);
    }