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.

RM46 bootloader with Flash ECC enabled

Other Parts Discussed in Thread: RM46L852, UNIFLASH

Hi,

I've got an Ethernet bootloader based on TIDM-ETHERNET_BOOTLOADER that can download an application that then runs with Flash ECC enabled.

This all works fine if the bootloader does not enable Flash ECC. The bootloader correctly programs the application into Flash, the application can then start running and enables Flash ECC at startup.

I would like to have the bootloader also run with ECC enabled, but with Flash ECC enabled the bootloader fails the erase check and program verify (which I understand).

I have tried disabling Flash ECC while doing the erase check, but it still fails because one memory location reads as 0xFFFBFFFF (my application is programmed starting at 0x020000, location 0x020004 reads 0xFFFBFFFF, but all the other words appear to be 0xFFFFFFFF as expected when Flash ECC is disabled).

Here's the code I am using to disable the Flash ECC while doing the erase check -

  // Disable Flash ECC while doing the erase check
  _coreDisableFlashEcc_();
  flashWREG->FEDACCTRL1 = 0x00000005U;
  status = Fapi_doBlankCheck((uint32_t *)Flash_Start_Address, (Size_In_Bytes >> 3), &erase_status);
  if (status != Fapi_Status_Success)
  {
    DebugPrintf("Erase failed!\r\n");
  }
  // Re-enable Flash ECC
  flashWREG->FEDACCTRL1 = 0x000A060AU;
  _coreEnableFlashEcc_();

From what I've read this should work. Any ideas on why it doesn't?

regards,

Charles

  • I forgot to add - I am using the RM46L852 with F021 Flash API 02.01.01.
  • Hello!

    Strange, _coreDisableFlashEcc_() works for me. I has similar results (0x020004 reads 0xFFFBFFFF) before implement disabling flash ECC Check

    This is my code:

    bool Flash_Erase_Check(const uint32_t Start_Address, const uint32_t Bytes) {
        register uint32_t *dst1 = (uint32_t *) Start_Address;
        register uint32_t bytes = Bytes;
        bool retcode = true;
    #ifdef TMS570
        _coreDisableFlashEcc_();
    #endif
    
        while (bytes > 0) {
            if (*dst1 != 0xFFFFFFFF) {
                LOG_ERROR(SYS, "Erase flash error at 0x%08" PRIX32 ". Data=0x%08" PRIX32, (uint32_t)dst1, *dst1);
                retcode = false;
                break;
            }
            dst1++;
            bytes -= 0x4;
        }
    #ifdef TMS570
        _coreEnableFlashEcc_();
    #endif
        return retcode;
    }
    

  • The problem may be that location 0x20000 is in the flash pipeline. (The pipeline mode acts like a very small cache.) To flush the data pipeline, after you disable ECC you can use the flash API function Fapi_flushPipeline().

     

       volatile uint32_t  u32DummyRead;
    
       u32DummyRead = *((volatile uint32_t *)0x000U);
       u32DummyRead = *((volatile uint32_t *)0x100U);
       u32DummyRead = *((volatile uint32_t *)0x200U);
       u32DummyRead = *((volatile uint32_t *)0x300U);
    

  • Thanks Bob, that seems like a sensible idea. Unfortunately adding that does not change the behaviour.
    If I make my bootloader ignore the erase check result and the program verify result I can see that the application has in fact been programmed in correctly. Often it will then fail a CRC check, but if I reset the board to restart it the CRC check will pass and it runs fine.
    I'll keep digging...

    regards,
    Charles
  • One thing I noticed is that I have a pre-production RM46L852 on my control card (the chip is marked xRM46). I'm not sure how I find the errata for that.

    Stepping through Fapi_doBlankCheck() it looks like it does in fact call Fapi_flushPipeline().

    regards,
    Charles
  • The xRM46L852 will be revision B silicon and the errata document is SPNZ200, but I don't think this is related to an erratum. If it fails the erase check, program verify and occasionally a CRC check, I suspect the flash is not erased well. You might want to double check that the device is running at the frequency passed in the call to Fapi_initializeFlashBanks() and that EWAIT is set properly.

  • You were right, Bob, I wasn't passing in the correct frequency, but there was a reason for that and unfortunately I still haven't got it working.

    I had forgotten that I when I first started getting this bootloader going I had problems getting Fapi_initializeFlashBanks() to return success.

    I am running the RM46L852 at 160MHz, which (according to the datasheet) should work with 2 data wait state and 0 address wait states, but with those settings Fapi_initializeFlashBanks() returns Fapi_Error_InvalidHclkValue.

    I have just tried setting HCLK to run at 80MHz with from 1 to 4 wait states and Fapi_initializeFlashBanks() returns Fapi_Status_Success, but the erase check still fails.

    Sounds like a similar problem to this post  

    regards,

    Charles

  • The RM46L852 should run at 160MHz and 2 wait-states. Can you provide me a memory dump of the TI OTP from location 0xF0080140-0xF0081FF? A snipping tool capture of a CCS memory window will do as long as it is readable.

    Did you try erasing again, or only doing the erase verify?
  • Hi Bob,
    Here's the memory dump:

    0xF0080140 - FFFF7F9E FFFFFFFF FFFF7F9E FFFFFFFF 001001F8 CC2A8E9E 00108102 01510500 77167401 00062849 7A280005
    0xF008016C - 00440034 22222A2A 030221A1 02540200 0200F019 01370020 00FF00C8 03E80010 00000FA0 01C901F7 0094071B
    0xF0080198 - 09040BFF A34F9E85 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF B241B2DB 161000DC FFFF0E22 370004FF 00030003
    0xF00801C4 - 0003FFFF 0004FFFF FFFF0004 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 344D5278 35384C36 54575A32 00000000
    0xF00801F0 - 00000000 00000000 00000000 00000000 05570561 0541FFFF 34303276 2909FFFF 05610556 0000FFFF 35993457

    I'd just been looking at this post
    e2e.ti.com/.../1595898
    and from looking at the value at address 0xF00817C (=0x200F019) it looks like the part I have needs 3 wait states at 160MHz.
    With 3 wait states at 160 MHz Fapi_initializeFlashBanks() returns success, but the erase check and program verify fail.

    >Did you try erasing again, or only doing the erase verify?
    Yes, each time I test it the code is doing the erase and then calling Fapi_doBlankCheck().

    One interesting thing I have noticed is that the blank check only fails at location 0x20004 and the program verify only fails at location 0x20000.

    Thanks.

    regards,
    Charles
  • Yes, this pre-production xRM46L852 requires 3 wait-states for erase or program at 160MHz. (150MHz is the 2 wait-state limit on this old device.) That still does not explain the problem programming and erasing. What happens if you use CCS to erase the flash at 0x02000000? I wonder if it is a real flash issue, or is this still an ECC problem? Were you still in SYSTEM mode when you did the call to _coreDisableFlashEcc_()?
  • Hi Bob,

    >What happens if you use CCS to erase the flash at 0x02000000?
    The debug configuration is set to erase the entire Flash.
    I ticked "Enable Verbose Output" in the "Flash Settings" in the Debug Configuration and the output indicates that it all works well.

    > I wonder if it is a real flash issue, or is this still an ECC problem?
    If I don't enable ECC in the bootloader at startup it all works fine, but I guess that we don't know whether it is a problem with the ECC not working properly, the ECC values not being erased/programmed properly or the program code not being erased/programmed properly.

    >Were you still in SYSTEM mode when you did the call to _coreDisableFlashEcc_()?
    It is in IRQ mode, because the EMAC driver interrupt calls straight into the LWIP stack and ends up calling my application code.

    regards,
    Charles
  • It might be worth double checking that LwIP did not put you back in user mode. If that were the case, the ECC disable would not work and that would explain the behavior. (Perhaps you can get a breakpoint in the _coreDisableFlashEcc() routine and check the CPSR for the mode.)

    As for erasing with CCS, you can select which sectors to erase in the On-chip Flash section. This snippet is from CCS6:

  • Hi Bob,
    Yes, it's definitely in IRQ mode, that's how I first checked it (using a breakpoint).
    I've added some test code to do an erase and program of sector 4 from my main loop to make it easier to check.

    Is there any way in CCS to erase Flash without downloading?

    regards,
    Charles
  • >Is there any way in CCS to erase Flash without downloading?

    I've just remembered about UniFlash - that does what I was thinking of.
  • Hi Bob,
    I think I've got it working.
    Changing the code that checks for a valid application in the Flash at 0x020000 changes the behaviour.
    I'll look into it in more detail tomorrow and post my findings.

    regards,
    Charles
  • Hi Bob,
    My code was checking to see if there was an application already programmed in Flash by reading the first location (0x20000), but without first disabling ECC. Address 0x20000 was always reading 0xFFFFFFFF if it had been erased so this appeared to work, except that subsequently trying to erase of program the Flash failed.
    Of course when I decided to improve the start up check by having it look at a signature value in a header at 0x200020 it generated a data abort if that sector was erased, which made me realise that I need to disable ECC when checking for blank Flash since the ECC will always be invalid when the Flash is blank.
    Disabling ECC while doing this startup check fixes the problem and then erasing and programming the Flash works fine.
    I guess I was just unlucky that when the Flash at 0x20000 is erased the first word reads 0xFFFFFFFF even with ECC enabled and doesn't seem to generate an ECC error.
    I'm not sure why that should cause the subsequent Flash blank check or program verify problems.

    Thanks for your help.

    regards,
    Charles

  • I think I understand what happened. When you read location 0x20000 and it was erased, you had data of 0xFFFFFFFF, 0xFFFFFFFF and ECC of 0xFF. The correct ECC for location 0x20000 and data of 0xFFFFFFFF, 0xFFFFFFFF for an RM part is 0x6D. XOR of 0x6D and 0xFF (the ECC value read) is 0x92, this is the syndrome. From the syndrome table, 0x92 means a single bit error in data bit 42. When you invert data bit 42, you get 0xFFFBFFFF at location 0x20004. When the Cortex R4 detects a single bit error, it writes the corrected value and the address to internal registers. All subsequent reads that match that address are now satisfied from the internal register instead of the flash. This minimizes the performance impact of a single, single bit error. Since this is in the CPU and not the flash wrapper, the pipeline flush routine had no impact. The only ways to invalidate the internal single bit correction register is by reading another location with a single bit error, or a CPU reset. To me it all makes sense now.