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.

ECC code and test example for F2837x?

Expert 1960 points
Other Parts Discussed in Thread: CONTROLSUITE, UNIFLASH, SYSBIOS

Hi Folks,

I was wondering if anyone has tried ECC feature available on F28377x, and any code snippet  that I can use to jump start? I searched controlSuite but could not find any. THis is a new MCU, but hopefully some friendly TI folks might be able to share some code snippet since they must have tested it on this chip. If possible I'd also like to test it with the built-in test mode in Linker. Many thanks in advance!

  • Shef,

    To Program ECC:

    (i) If you want to program ECC for the Flash using Flash API in your application, you can look at the flash_programming example provided in Controlsuite (controlSUITE\device_support\F2837xD\vx\F2837xD_examples_Dual\flash_programming). You can use "Fapi_AutoEccGeneration" as the programming mode when calling "Fapi_issueProgrammingCommand()" function from Flash API. In this programming mode, Flash API will calculate the ECC and program the ECC along with the Flash main array contents. This programming mode expects either 64-bits (minimum) or 128-bits (maximum) of main array data since 8-bits of ECC gets calculated for every 64-bits of ECC. Any unprovided data (in 64-bits) for a 64-bit aligned address will be assumed as all 1s to calculate the ECC. Once ECC gets programmed, you can not program any 1s as 0s in that 64-bit data.

    (ii) If you want to program ECC for your coff file using CCS Flash Plugin or UniFlash tool, you can use (enabled by default) "AutoEccGeneration" option in GUI of these tools. When this feature is enabled in the tools, ECC will be generated and programmed by the tool along with the Flash main array contents.

    To use ECC when reading Flash:

    Once you program ECC with one of the above options, you should be able to use ECC feature while reading/executing from Flash. ECC feature is enabled by default. Check out the FLASH_ECC_REGS (base address for these registers is 0x5FB00) in TRM. InitFlash() function in F2837xD_SysCtrl.c file enables the ECC.

    Thanks and regards,
    Vamsi
  • Hi Vamsi,
    Thanks for your insight! I've used Fapi_AutoEccGeneration mode to write an example application into flash. It's also enabled at startup by calling initFlash(), as you mentioned. Now, how do I test/verify that it is working? For example, what happens if there is an error, correctable or uncorrectable, detected in run time? The TRM says that it will cause an NMI, so I suppose that I need to enable NMI. Is there any easy way to simulate/inject an error via CCS, or only have to use linker cmd file?

    Another question is, where to find similar code for RAM? I don't even see register definition in controlSuite. It'd be great if you can provide some code snippet since you've use it. Thanks again!
  • Shef,

    There are test registers in the flash wrapper available for you to use. You can write data and ECC to these registers and start the tests. Please see the Flash register section of the TRM. You can test to make sure your flash wrapper is working properly and identifying the errors you inject into the test data or test ECC.

    Below are the test registers you can use.
    FDATAH_TEST
    FDATAL_TEST
    FADDR_TEST
    FECC_TEST
    FECC_CTRL
    FOUTH_TEST
    FOUTL_TEST
    FECC_STATUS

    An NMI will always be triggered for any uncorrectable error. You can set a threshold for single-bit errors which are correctable. Once the number of single-bit errors hit that threshold, the SINGLE_ERR_INT flag is set and an interrupt is fired.

    sal
  • Shef,

    Flash ECC test mode that Sal mentioned is explained in section "2.12.10.3 SECDED Logic Correctness Check" of the TRM.

    Note that the code that uses this test mode should be executed from RAM and not from Flash since Flash gets bypassed when the ECC test mode is enabled. If you want to try this test mode, you can use Fapi_calculateEcc() function in Flash API to get ECC value for your chosen address and 64-bit data. Fapi_CalculateEcc() function needs a byte address (left shift the C28x Flash address by 1 position before passing it to this function). You can insert errors in the data/address before writing to the test mode registers. All of this is explained in above section of the TRM.

    Regarding your question on RAM: Are you asking about RAM ECC?

    Thanks and regards,
    Vamsi
  • Hello Sal, Vamsi

    Thank you both so much for your detailed info. I felt thrilled to have two experts helping me on this.

    As a typical (lazy) user, I'm looking for a quick way to test ECC. I've built a flash-based simple app (say blinky_cpu01), and I loaded it into flash with "Auto ECC Generation" selected in CCS On-Chip Flash, so I assumed that it has ECC built-in to the flash memory. I've also got ECC enabled in InitFlash() at startup, and NMI ISR setup. I can run it from flash now, but I want to verify that it will enter NMI if a memory error happens. I read in C28 Assembly manual that there are two command-line options that inject bit errors into the linked executable. So I tried:
    -ecc:data_error=0x86000, 0x01

    But the linker reported an error
    error #10416: error specified at 0x86000 does not lie withink an ECC input or output range.

    I tried different memory addresses, but it always reported error, sometimes saying that it's not within "initialized range" (when I set it to Flash ECC location at 0x1080000).

    What else should I do to get it enter NMI without modifying my application code? I read the TRM section on these registers. It seems that I have to write a separate program to run in RAM along side with my app code in order to test ECC. If this is the only way to test the ECC, I guess that I have to do it. Thanks!
  • Shef,

    Linker team is working on fixing these issues. Hence, we suggested the ECC test mode.

    If you want to test your NMI ISR for ECC errors, you can use below addresses (these locations will be documented in the next version of TRM) in F2837x devices. These errors are inserted by TI for your convenience.

    (1) 64-bit data at address 0x701F8 will have a single-bit error.
    (2) 64-bit data at address 0x701FC will have a double-bit error.

    You can make your application to read these locations and your application should catch both single bit and double bit errors at these locations.

    Thanks and regards,
    Vamsi
  • Hi Vamsi,
    Thanks for the info that linker option does not work at the moment, if I understand you correctly. Please let me know once it's fixed.
    Now I guess that I've to write test code to trigger NMI. You guys must have tested this mode many times before documenting it in TRM. Therefore, it comes to my original request, can you share some example code snippet for ECC test? I does not have to be perfect or clean, but would still help me to move forward. TRM is good but it does not always explain what exactly to do in the code. I'd really appreciate if you can drop anything useful. Thanks and have a nice weekend!
  • Shef,

    Below are some code snippets that you can use to setup your NMI ISR and single bit error ISR.  

    (1) You can define your single bit error ISR something like below:

    interrupt void Flash_SingleError_ISR(void)
    {

    EALLOW;

    Flash0EccRegs.ERR_INTCLR.bit.SINGLE_ERR_INTCLR = 1;

    SingleErrIntrptISRTaken = 1; /*Used to know whether the ISR got executed or not*/

    PieCtrlRegs.PIEACK.all |= 0x800; // Issue PIE ACK

    EDIS;

    }

    (2) You can define your NMI ISR something like below:

    interrupt void local_NMI_ISR (void)
    {

    EALLOW;

    if((NmiIntruptRegs.NMIFLG.bit.NMIINT == 1) && (NmiIntruptRegs.NMIFLG.bit.FLUNCERR == 1))

    {

    NmiIntruptRegs.NMIFLGCLR.bit.FLUNCERR = 0x1;
    NmiIntruptRegs.NMIFLGCLR.bit.NMIINT = 0x1;

    }

    Flash0EccRegs.ERR_INTCLR.bit.UNC_ERR_INTCLR = 1;

    NMIISRTaken = 1; /*Used to know whether the ISR got executed or not*/

    EDIS;

    }

    (3) You can map the ISRs that you defined in your code to the PIE Vector table as below.

    EALLOW; 
    PieVectTable.FLASH_CORRECTABLE_ERROR_INT = &Flash_SingleError_ISR;
    PieVectTable.NMI_INT = &local_NMI_ISR;
    EDIS;

    (4) Enable the interrupts required as below:

    EALLOW;
    PieCtrlRegs.PIEIER12.bit.INTx11 = 1; //C28FLSINGERR
    IER = 0x800; // Enable CPU INT
    ERTM;

    (5) Clear NMIFLG before enabling NMI

    EALLOW;
    NmiIntruptRegs.NMIFLGCLR.all = 0xFFFF;
    EDIS;

    (6) Enable NMI

    EALLOW;
    NmiIntruptRegs.NMICFG.bit.NMIE = 0x1;
    EDIS;

    (7) Then enable ECC and throw reads to the locations that I provided in my earlier reply in this thread.  Put breakpoints in the ISRs and you should see control going to the ISRs.  If you throw reads to the locations at which you programmed ECC using AutoEccGeneration option, you should not get ECC errors.

    Does this help?  Above code snippets are taken from my test cases and hence the names of the bit-fields might be a little different than that of what you got from controlsuite. 

    This procedure should be good for what you wanted to check.  If you want the code to try the ECC test mode as well, I can share it with you next week.  

    Thanks and regards,

    Vamsi

  • Thank you thank you Vamsi!!! That's exactly what I've been looking for, and even better! I'll try it out and let you know how it goes. Have a great weekend!
  • Hi Vamsi,
    I used your code and read the 2 OTP locations you provided earlier. However, reading of both locations will all lead to NMI ISR. I set Flash0EccRegs.ERR_THRESHOLD.all = 3, and read 16 or 64-bit value (long long int) at 0x701F8. I expected it to enter the SingleError_ISR at least 3 times before entering NMI ISR. But it always enters NMI ISR as soon as I read the value at 0x701F8 (or 0x701FC), never enters the SingleError_ISR once. Here is how I read it in the code:
    long long int testval=0, *testadd;
    testadd = 0x701F8; // location with correctable error;
    testval = *testadd;
    Did you guys try it before, and what did I miss?
  • Hi Vamsi,
    ANother question regarding NMI: when an NMI such as noncorrectable error is triggered and the CPU entered NMI ISR, should the "Error Pin" (also called ERRORSTS?) become high automatically? This is my understanding according to the 377x TRM (Section 2.6.8). But on my 377D control Card, ERROR pin (measured at TP01) remains unchanged before and after NMI. How do I get Error pin to work?
  • Hi Shef,

    As mentioned in the TRM, there are two SECDED modules in the Flash wrapper. Out of the 128-bits returned from Flash/OTP for an access, both the lower 64-bits and the upper 64-bits are evaluated for ECC in parallel. Hence, although ECC is calculated on 64-bit basis, a read of any address location within a 128-bit aligned Flash memory will cause the un-correctable error flag to get set when there is a un-correctable error in both or in either one of the lower 64 and upper 64 bits of that 128-bit data. NMI will occur for a read of any address location within a 128-bit aligned Flash memory, when there is an un-correctable error in both or in either one of the lower 64 and upper 64 bits of that 128-bit data. In this case, since single-bit error and un-correctable error exist in the same 128-bits, NMI is occurring even when you read the lower 64-bits (0x701F8). NMI is of higher priority than the single-bit ISR and hence you noticed that the control is reaching NMI ISR.

    Thanks and regards,
    Vamsi
  • Hi Shef,

    Regarding the error pin: Did you check the status of the error pin before clearing the uncorrectable error flag and NMIFLG?

    Thanks and regards,
    Vamsi
  • Hi Vamsi,
    I put a break point at the beginning of local_NMI_ISR() and watched the Error Pin from TP1 on 377D ControlCard. It went into NMI_ISR but the error pin stays low during the whole time even when I stepped through to the end of ISR and out. Further more, I also noticed that the error pin would go high after I connected the mini-USB to PC for XDS100v2 emulator. Wondering if this is normal?

    Thanks for your explanation on 128-bits. I guess that we cannot test single correctable error in this way. That's ok if not. A more critical question is: is there any similar way to test ECC for RAM as we do for Flash? Sorry for bombarding you with all these questions, but it'd be great to get all those answered while I still have your attention. Thanks a lot!
  • Hi Shef,

    Regarding single-bit error: In this case, since you know that reading those locations will cause single bit error as well, you can confirm the same in the NMI ISR by reading the single bit error address registers.

    Regarding the RAM ECC test mode: Please check section "2.11.1.9 Application Test Hooks for Error Detection and Correction" in TRM.

    It would be good if you can start a new thread on the error pin so that our System Control experts can answer you.

    Thanks and regards,
    Vamsi
  • Hi Vamsi,
    OK I'll start a new thread about Error pin. That's a good idea and hopefully you'll be still around to read it...

    One last question still relevant: can you share some code snippet on ECC test mode? I appreciated it that you offered to provide it last Friday. I could really use it now since I cannot test it simply with a fixed OTP address for RAM. Thanks a lot for this wonderful session of support which is tremendous!
  • Shef,

    Thank you.
    Are you asking the code for RAM ECC test mode or Flash ECC test mode?

    Thanks and regards,
    Vamsi
  • Hi Vamsi,
    Can I have both? :-) If not, I'd chose RAM since Flash can be tested with the OTP address you provided.
    Actually, what is the register name for RAM ECC, the counterpart of FlashEccRegs for Flash?
    For Flash, the register name is Flash0EccRegs in the code (with '0' in the name), but I assume that it covers the whole Flash range, not just Flash Sector 0 as it might suggest?
  • Shef,

    RAM registers are MEM_CFG_REGS.
    And the registers that you need to configure for RAM ECC/parity test mode are DxTEST, LSxTEST, GSxTEST and MSGxTEST.

    For Flash: Yes, Flash0EccRegs cover the entire Flash range and not just sector 0.

    I will provide the Flash ECC test mode example code to you sometime this week. I will check on the RAM ECC test mode example and let you know.

    Thanks and regards,
    Vamsi
  • Vamsi,
    THANK YOU! You guys are awesome! Hopefully your answers and code snippet will benefit not just me, but all other users in the world too, one at a time.
  • HI Vamsi,
    Sorry for continue to bother you with this issue again. I tried to add the same ECC test code in my real project which uses SYS/BIOS. But I could not get it to work somehow. It just won't enter NMI ISR. Although this project uses SYS/BIOS, but I put the test code at the beginning of main. I also removed "TYPE=DSECT" from F2837xD_Headers_BIOS_cpu1.cmd in order to allocate PIE_VECT in the same way as non-BIOS project. EVerything else seems to work fine except that it won't enter NMI ISR even after the code reads the OTP location with ECC error. Is there anything that I need to do for NMI with SYS/BIOS project, beyond using your code snippet? Thanks!
  • Shef,

    SYS/BIOS takes ownership of the interrupt vector table.

    If you want to plug the NMI vector (#18), add the following to your .cfg file:

    var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');
    Hwi.plugMeta(18, `&yourNmiFunction`); /* replace with the name of your NMI function */

    I hope this helps.

    Alan
  • Thanks Alan! This looks encouraging! I added the 2 lines into my .cfg file (the 1st line var Hwi is duplicated but I guess no harm to have it again), and removed my old NMI configuration code (using PIE as provided by Vamsi earlier). But it would not enter NMI at all after reading the error location in OTP. Is there anything else needed besides these two lines in .cfg file? By any chance, can you have a SYS/BIOS based example which has NMI defined in .cfg? An example worth thousand words... Many thanks!
  • Are you sure an NMI is being generated when the error location is read?

    Sadly, we don't have any NMI example code.

    Alan

  • Hi Alan,
    I used the method recommended by Vamsi earlier to read a specific location in OTP. It generates NMI and enters the NMI ISR correctly when I tested this in a simple blinky example which sets PIE table etc. But the same code won't work in SYS/BIOS, even after I add the code in .cfg to plug the ISR into Hwi 18. I'm not sure if NMI is generated at all as I don't see any changes in NmiIntrup register, or it does but just not enter ISR correctly. Do you have any suggestion how to troubleshoot this? Thanks!
  • Can you confirm that the NMIE bit (bit 0) in the NMICFG register (at 0x00007070) is set?
    You may have to add code to your application to explicitly enable the NMI.
  • Hi Alan,

    I ran the following lines of code to config NMI, in addition to your 2 lines in .cfg line to plug-in NMI ISR:

    //(5) Clear NMIFLG before enabling NMI
    EALLOW;
    NmiIntruptRegs.NMIFLGCLR.all = 0xFFFF;
    EDIS;

    //(6) Enable NMI
    EALLOW;
    NmiIntruptRegs.NMICFG.bit.NMIE = 0x1;
    EDIS;

    Here is a screenshot of NMI registers in run time after it reads the OTP address with ECC error.  NMIFLG is 0x0001as it mapped to 0x7060. You mentioned 0x7070 for NMICFG but it maps to XintRegs which has 0x0000. Is this normal?

  • My bad regarding the base address.

    It looks like the NMI is enabled. But there is no NMI pending (NMIFLG bit 0).

    At this point in the code, have you already triggered the NMI?

    Also, it looks like the watchdog timer has not begun counting.

    Alan