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.

TMS320F28377S: ADC-PPB trip-zone flag is set if flash ECC is tested during power up

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

Hi,

I use the power on self tests (POSTs) that we have been using in one of our previous projects to do the POSTs on a motor controller based on F28377S. Those POSTs use TI's STL library. If I allow the POSTs to execute the flash ECC test, then I get the ADC-PPB (post processing block) trip zone flag set when the code is running. The flash ECC POST is based on the STL example provided by TI. It works. However, flash ADC-PPB trip-zone flag is set when I activate the POST. Attached documents shows the details of the trip-zone and ADC settings.  

Do you know possible reason for this behavior?

Thanks,

Dhammika4604.tripzone_isssue.docx

  • Hi Dhammika,

    Our ADC expert will get back to you in a day or two.

    Thanks and regards,
    Vamsi

  • Dhammika,

    I spoke to some others, and there is not any obvious tie in here.  I believe the Flash ECC test is simply reading flash locations and looking for an ECC fault(that would be captured automatically on any memory read).

    Is the ADC actively converting when the ECC test is called?  The PPB can only trip on new conversions, I'd like to start to rule out any interference, perhaps stopping the ADC while the test is called to see if the issue still occurs?

    Best,

    Matthew

  • Hi Matthew,

    Thanks for the quick reply. I have attached the flash ECC test code below. It is based on the STL example provided by TI. One notable thing is that the person who wrote this part of the code did not init the flash API before calling these functions. So, I thought that was causing the issue. I corrected that problem but this issue never went away. 

    POST (which has the flash ECC test inside) is the very first thing done in the main program. ADCs are initialized after initializing PIE etc. However, the PWM is set up before the ADCs are set up. After setting up the ADC, a conversion forced by software is done. But at that point, the PPB trip zone events have not been activated. PPB trip-zone events are activated only after PWM is linked to the ADCs and the motor control ISR starts to work. At that point PPBs have been set up properly. I checked this sequence and it seems to be correct. If the flash ECC test is done inside the POST, it seems the PPB trip-zone flags are set even if the PPB trip-zone is not activated.  What I mean by activation of the PPB trip-zone is executing the following code.

    void enableADC_PPB_Tripzone(void)
    {
    Ph_A_ADC.ADCPPB3CONFIG.bit.CONFIG = 0; // PPB 3 is associated with SOC0
    Ph_A_ADC.ADCPPB3OFFCAL.bit.OFFCAL = 0;
    Ph_A_ADC.ADCPPB3TRIPHI.bit.LIMITHI = ADC_PPB_HI_LIMIT; // Hi limit of ADC PPB output
    Ph_A_ADC.ADCPPB3TRIPHI.bit.HSIGN = 0; // sign bit
    Ph_A_ADC.ADCPPB3TRIPLO.bit.LIMITLO = ADC_PPB_LO_LIMIT; // Lo limit of ADC PPB output
    Ph_A_ADC.ADCPPB3TRIPLO.bit.LSIGN = 0; // sign bit

    Ph_A_ADC.ADCEVTSEL.bit.PPB3TRIPHI = 1; // Setting this flag causes the ADCAEVT3 to be asserted when PPB's high limit is violated.
    Ph_A_ADC.ADCEVTSEL.bit.PPB3TRIPLO = 1; // Setting this flag causes the ADCAEVT3 to be asserted when PPB's low limit is violated.

    Ph_B_ADC.ADCPPB4CONFIG.bit.CONFIG = 1; // PPB 4 is associated with SOC1
    Ph_B_ADC.ADCPPB4OFFCAL.bit.OFFCAL = 0;
    Ph_B_ADC.ADCPPB4TRIPHI.bit.LIMITHI = ADC_PPB_HI_LIMIT; // Hi limit of ADC PPB output
    Ph_B_ADC.ADCPPB4TRIPHI.bit.HSIGN = 0; // sign bit
    Ph_B_ADC.ADCPPB4TRIPLO.bit.LIMITLO = ADC_PPB_LO_LIMIT; // Lo limit of ADC PPB output
    Ph_B_ADC.ADCPPB4TRIPLO.bit.LSIGN = 0; // sign bit

    Ph_B_ADC.ADCEVTSEL.bit.PPB4TRIPHI = 1; // Setting this flag causes the ADCBEVT4 to be asserted when PPB's high limit is violated.
    Ph_B_ADC.ADCEVTSEL.bit.PPB4TRIPLO = 1; // Setting this flag causes the ADCBEVT4 to be asserted when PPB's low limit is violated.

    Ph_C_ADC.ADCPPB2CONFIG.bit.CONFIG = 0; // PPB 2 is associated with SOC0
    Ph_C_ADC.ADCPPB2OFFCAL.bit.OFFCAL = 0;
    Ph_C_ADC.ADCPPB2TRIPHI.bit.LIMITHI = ADC_PPB_HI_LIMIT; // Hi limit of ADC PPB output
    Ph_C_ADC.ADCPPB2TRIPHI.bit.HSIGN = 0; // sign bit
    Ph_C_ADC.ADCPPB2TRIPLO.bit.LIMITLO = ADC_PPB_LO_LIMIT; // Lo limit of ADC PPB output
    Ph_C_ADC.ADCPPB2TRIPLO.bit.LSIGN = 0; // sign bit

    Ph_C_ADC.ADCEVTSEL.bit.PPB2TRIPHI = 1; // Setting this flag causes the ADCCEVT2 to be asserted when PPB's high limit is violated.
    Ph_C_ADC.ADCEVTSEL.bit.PPB2TRIPLO = 1; // Setting this flag causes the ADCCEVT2 to be asserted when PPB's low limit is violated.

    }

    Thanks,

    Dhammika

    #include <stdlib.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include "stl_flash.h"
    #include "stl_util.h"
    #include "F021_F2837xS_C28x.h"   //for Fapi_calculateEcc
    #include "crc_tbl.h"
    
    #include "post.h"
    
    #define MAX_NUM_CRCS (10)
    
    //Linker generated object(CRC table)
    extern CRC_TABLE flash_crctbl;
    
    bool flashCrcChecks[MAX_NUM_CRCS];
    
    //TI function from ref_crc.c (see UsbLanIf_Ti_DeviceSupport project)
    //used to compute CRC values.
    Uint32 gen_crc(int16 id, const Uint16 *data, size_t len);
    
    // Flash ECC Logic test values
    #define FLASH_DATAL        0x87654321UL
    #define FLASH_DATAH        0xFEDCBA09UL
    #define FLASH_ADDR         0x00090000UL
    #define FLASH_DATA64       0xFEDCBA0987654321ULL
    
    
    // Flash ECC Logic test object
    STL_Flash_ECCLogicObj flashECCTestObj;
    
    /*-----------------------------------------------------------------------------
     *
     *  CheckFlashEccLogic
     *
     *  Routine to test the Flash ECC logic. We perform multiple tests with
     *  corrupted data which should result in failing all the tests.
     *
     *  Parameters: None.
     *
     *  Returns: A TestStatus value of tsPassed if all the Flash ECC tests pass,]
     *           otherwise tsFailed.
     *
     */
    TestStatus CheckFlashEccLogic()
    {
        Uint16 testStatus = STL_FLASH_ECC_LOGIC_FAIL;
    
        //Initialize the Flash ECC Logic test object
        EALLOW;
        Uint16 ecc = Fapi_calculateEcc(FLASH_ADDR << 1, FLASH_DATA64);
        EDIS;
    
        flashECCTestObj.dataLow        = FLASH_DATAL;
        flashECCTestObj.dataHigh       = FLASH_DATAH;
        flashECCTestObj.address        = FLASH_ADDR;
        flashECCTestObj.ecc            = ecc;
    
        // Operate on the low ecc block.
        flashECCTestObj.eccBlockSelect = STL_FLASH_ECC_BLOCK_LOW;
    
        // Data Low single bit error corruption in bit 7.
        flashECCTestObj.dataLow = FLASH_DATAL ^ 0x80;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.dataLow = FLASH_DATAL;
    
        // Data High single bit error corruption in bit 30 (62).
        flashECCTestObj.dataHigh = FLASH_DATAH ^ 0x40000000;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.dataHigh = FLASH_DATAH;
    
        // ECC single bit error corruption in bit 2.
        flashECCTestObj.ecc = ecc ^ 0x04;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.ecc = ecc;
    
        // Uncorrectable error in address bit 11.
        flashECCTestObj.address = FLASH_ADDR ^ 0x00000800;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.address = FLASH_ADDR;
    
        // Uncorrectable error in data bits 0 and 24.
        flashECCTestObj.dataLow = FLASH_DATAL ^ 0x01000001;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.dataLow = FLASH_DATAL;
    
        // Operate on the high ecc block.
        flashECCTestObj.eccBlockSelect = STL_FLASH_ECC_BLOCK_HIGH;
    
        // Data Low single bit error corruption in bit 7.
        flashECCTestObj.dataLow = FLASH_DATAL ^ 0x80;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.dataLow = FLASH_DATAL;
    
        // Data High single bit error corruption in bit 30 (62).
        flashECCTestObj.dataHigh = FLASH_DATAH ^ 0x40000000;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.dataHigh = FLASH_DATAH;
    
        // ECC single bit error corruption in bit 2.
        flashECCTestObj.ecc = ecc ^ 0x04;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.ecc = ecc;
    
        // Uncorrectable error in address bit 11.
        flashECCTestObj.address = FLASH_ADDR ^ 0x00000800;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
        flashECCTestObj.address = FLASH_ADDR;
    
        // Uncorrectable error in data bits 0 and 24.
        flashECCTestObj.dataLow = FLASH_DATAL ^ 0x01000001;
        testStatus &= STL_Flash_testECCLogic(&flashECCTestObj);
    
        flashECCTestObj.dataLow = FLASH_DATAL;
    
        //The ECC logic tests passed if they all returned STL_FLASH_ECC_LOGIC_FAIL (1).
        //If any returned STL_FLASH_ECC_LOGIC_PASS (0), then the ECC logic test failed
        //and test Status will be STL_FLASH_ECC_LOGIC_PASS (0).
        return (STL_FLASH_ECC_LOGIC_FAIL == testStatus) ? tsPassed : tsFailed ;
    }
    
    /*-----------------------------------------------------------------------------
     *
     *  CheckFlashCrcValues
     *
     *  Routine to check the sections of flash memory have CRCs that match what
     *  was calculated by the linker.
     *
     *  Note: The TI default CRC32_Prime algorithm is used.
     *
     *  Parameter:  None
     *
     *  Return: A TestStatus value of tsPassed if all CRC values match, otherwise
     *          tsFailed.
     *
     */
    TestStatus CheckFlashCrcValues()
    {
        int16 numRecs = flash_crctbl.num_recs;
    
        for (int16 i = 0; i < numRecs; i++)
        {
            CRC_RECORD crcRecord = flash_crctbl.recs[i];
    
            //Now calculate the CRC
            Uint32 crcCalculatedValue = gen_crc(crcRecord.crc_alg_ID,
                                                       (Uint16 *)crcRecord.addr,
                                                       crcRecord.size);
    
            //Record whether the CRC value from the linker matches what we just calculated.
            flashCrcChecks[i] = (crcRecord.crc_value == crcCalculatedValue);
        }
    
        bool returnVal = true;
    
        int16 maxCheck = (numRecs > MAX_NUM_CRCS) ? MAX_NUM_CRCS : numRecs;
    
        for (int16 j = 0; j < maxCheck; j++)
        {
            returnVal &= flashCrcChecks[j];
        }
    
        //If any of the CRC checks fail, note the error.
        if (false == returnVal)
        {
            STL_Util_setErrorFlag(STL_UTIL_FLASH_DETECT);
        }
    
        return (returnVal) ? tsPassed : tsFailed ;
    }
    
    

  • Dhammika,

    I'm working to re-create this on my end, please give me until the 21st  to reply back on this topic.

    Best,

    Matthew

  • Thanks very much Matthew.

    Dhammika

  • Dhammika,

    For reference I'm using the following example code f2837xd_test_application project from the diagnostic libraries that have the STA tests: C:\ti\c2000\C2000Ware_1_00_01_00\libraries\diagnostic\f2837xd\examples\cpu1\test_application\  I'm assuming this framework is what is being called for your POST, but let me know if this is not the case.

    Inside this example code in sta_tests.c we define a test array of the various IP to test on the device:

    const STA_Tests_Types STA_Tests_testArray[STA_TESTS_NUMBERS] =
    {
        STA_TEST_START,
        STA_BROM_CPU1,
        STA_BROM_CPU2,
        STA_BROM_CRC,
        STA_INT_POST_TEST,
        STA_HWBIST_MICRO,
        STA_HWBIST_FULL,
        STA_CLA_MICRO,
        STA_CLA_FULL,
        STA_DEVCFG,
        STA_PER_REG,
        STA_ERRORSTS,
        STA_TEST_PIE_RAM,
        STA_TEST_PIE_HANDLER,
        STA_OSC_CT,
        STA_OSC_HR,
        STA_TIMER_POST,
        STA_TIMER_PEST,
        STA_MCD,
        STA_WD_TEST,
        STA_INT_MON,
        STA_SCI_MON,
        STA_SCI_TEST,
        STA_SPI_TEST,
        STA_I2C_TEST,
        STA_MCBSP_TEST,
        STA_CAN_TEST,
        STA_SP_TEST,
        STA_FLASH_ECC_LOGIC_TEST,
        STA_FLASH_ECC_DETECT,
        STA_FLASH_CRC,
        STA_RAM_LOGIC_TEST,
        STA_RAM_DETECT,
        STA_MARCH,
        STA_MARCH_COPY,
        STA_GPIO_INPUT_TEST,
        STA_GPIO_OUTPUT_TEST,
        STA_PWM_DUTY_TEST,
        STA_PWM_TRIP_TEST,
        STA_EQEP_TEST,
        STA_SDFM,
        STA_ADC_DAC_TEST_12BIT,
        STA_ADC_DAC_TEST_12BIT_DMA,
        STA_ADC_DAC_TEST_16BIT,
        STA_ADC_DAC_TEST_16BIT_DMA,
        STA_TEST_END
    };

    const STA_Tests_Types STA_Tests_testArray[STA_TESTS_NUMBERS]

    If I limit the test call to just the Flash ECC tests, I do not see any activity in the ADC PPB registers or ADC registers in general.

    From above there are unique tests for the ADCA/B/C/D, if these are called it will setup the ADCs to sample as well as use the PPB registers.

    Per how the example is setup it will iterate through all the tests above, but I would need to understand how this got implemented(if not using the example) in your system. 

    If you could let me know the deltas in the code you are debugging and this example we can go from there.  I'm wondering if in your system the ADC STA tests got lumped into the one big group of tests, etc.

    Best,

    Matthew

  • Hi Matthew,

    Thanks very much for testing this. In our code, tests have been arranged in the following sequence. From the names of the enumerators you can tell what the tests are. The tests are identical to the tests in the STL example. 

        ptFlashEccLogic,
        ptFlashCrc,
        ptHwbist,
    
        ptPie,
        ptInterruptVectorTable,
        ptInterruptVectorMismatchHandling,
    
        ptWD,
    
        ptIntOscillator2,
        ptXtalOscillator,
        ptIntOscillator1,
    
        ptTimer0,
        ptTimer1,
        ptTimer2,
    
        ptMemoryEccLogic,
        ptMemoryParityLogic,
        ptRam,
    
        ptSpiA,
        ptSpiB,
    
        ptSciA,
        ptSciB
    

    Thanks,

    Dhammika

  • Dhammika,

    Going back to your 1st post, you mentioned the function

    void enableADC_PPB_Tripzone(void){...}

    Did you mean that this function is getting called by the ECC POST tests, or just that whatever is happening in your system is mimicking what is in that function?  Would it be possible to put a breakpoint at that function to see if we trigger it with any of the other function calls?  From the construction of the example since we are not calling it, we shouldn't expect to trigger the BP, but will be good to confirm that.

    Best,

    Matthew

  • Hi Matthew,

    Currently, this function is called within the motor ISR after the ADC offsets have been calibrated. 

    Even if I do not call this function,  PPB trip-zone flags are set. That is why I said I am a bit puzzled by the trip-zone behavior. 

    I have called this function during init and activated all trip zone triggers during init. That did not solve the issue. The only decent solution was to disable the flash ECC tests. Then trip-zone flags are not triggered (for no reason) and the motor runs.

    Thanks,

    Dhammika

  • Dhammika,

    Let me loop in some of the team that owns the PPB trip zone, I think there are multiple factors in play.  There isn't any obvious link to the ECC test and the PPB that I can see on my end, but I'm wondering if there is 2nd factor with the offset calibration.

    Best,

    Matthew

  • Dhammika,

    I'd like to use the HW Watchpoints we have on the C2000 to try and catch the code that is setting the ADC PPB.  This is a bit of a process to set up if you haven't used them before, but will try and walk us through it :)   We will set up the below before you run the sta tests

    1)We need to specify the address range of the ADC PPB registers, and so we will need to clarify which ADC is giving this behavior.  For example if it is ADCA PPB, then the registers are from 0x7440-0x745F.  If this is ADCB/C/D we will just need to change the address accordingly.

    2)In CCS top toolbar go to View->Breakpoints

    3)Right click in the breakpoint window that just opened up and hover over the top item in the menu "Breakpoint (Code Composer Studio) then select HW Watchpoint

    4)In the pop up window just enter the 1st address of the ADC PPB block of interest, assuming it is ADC A we would enter 0x7440, and leave the "memory" selection as "write" Click OK.

    5)This should populate a new row in the Breakpoints window.  Right click on this entry and then select Breakpoint Properties

    6)Expand the HW configuration then Type the Trigger Type.

    7)You will see the 0x7440 in the location field.  We now want to add some mask bits so we can look at the whole PPB address range.  Since we want to look at all addresses in the 40-5F range, we will put 0x001F in the mask field, then click apply and close.

    8)Now run the program.  The HW Watchpoint will monitor the bus for data writes to the PPB registers and will break out if there is a memory write.  Since this action happens after the write occurs the code will be halted a few lines of code past the offending instruction, and hopefully we can use this info to see what code we have executed that caused this issue.  We can then start backtracking (with normal SW breakpoints) to understand how we got into this code.

    Let me know if you have questions or issues getting this to work.

    Best,
    Matthew

  • Hi Matthew,

    Thanks for these instructions. I tried it, but the trip-zone trigger flag is set when nothing is written to the PPB registers. 

    I found one thing though. EPwm7Regs.TZFLG.bit.DCBEVT1 and DVBEVT2 are set jut when the PWM ISR is configured. These two event flags corresponds to Flash ECC error (based on my code). The PWM ISR configuration code is given below. I do not know why that happens. This is the beginning of the issue. The OST flag is set once the serial communication starts. I have not yet found what causes that.

    Thanks,

    Dhammika

    void MapAndEnablePWM_ISR(void)
    {
        EALLOW;
    
        //PWM1 INT is used to trigger Motor Control ISR
        EPwm7Regs.ETSEL.bit.INTSEL = ET_CTR_PRD;    // INT on PRD event
        EPwm7Regs.ETSEL.bit.INTEN  = 1;              // Enable INT
        EPwm7Regs.ETPS.bit.INTPRD  = ET_1ST;         // Generate INT on every event
    
        PieVectTable.EPWM7_INT = &MotorControlISR;
    
        PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable the PIE block
        PieCtrlRegs.PIEIER3.bit.INTx7 = 1;  // Enable PWM1INT in PIE group 3
    
        EPwm7Regs.ETCLR.bit.INT=1;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable the PWM time-base clock
    
        EDIS;
    
        EALLOW;
        IER |= M_INT3; // Enable group 3 interrupts
        EDIS;
    }
    

  • Hi Matthew,

    Sorry, it seems I pressed the wrong button. The issue has not been resolved yet. 

    Anyway, the the PWM interrupt config code, the instruction that caused DVBEVT to set was:

    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable the PWM time-base clock

    Thanks,

    Dhammika

  • Dhammika,

    I think there must be a register in the PWM that is not initialized/re-initialized coming out of STA tests and as soon as we enable the PWM time base it is giving a false trip(based on conditions that are stale/not ready to be sampled).  I'm going to ask some others to take a look here.

    Best,
    Matthew

  • Hi Matthew, 

    It could be the reason, but I do not know what register it could be. I do not test the PWM modules in self-tests. 

    Thanks,

    Dhammika

  • Dhammika,

    Could you share the settings for these registers in your code:

    TZSEL

    TZDCSEL

    TZCTL

    TZCTL2

    TZCTLDCA

    TZCTLDCB

    It will help us understand the trip conditions.

    Best,
    Matthew

  • 1106.tripzone_isssue.docx

    Hi Matthew,

    Everything is in section 2 of the attached file. 

    Thanks,

    Dhammika

  • Hi Dhammika,

    Thank you for sharing your code. I am taking a look through the EPWM registers. 

    EPwm7Regs.TZFLG.bit.DCBEVT1 and DVBEVT2 are set jut when the PWM ISR is configured. These two event flags corresponds to Flash ECC error (based on my code)

    Can you please share how DCBEVT1 and DCBEVT2 correspond to Flash ECC errors? When I checked the code you provided I see the following statement:

    // ECC Error
        gPWM_TrippedByECC_Err = (NmiIntruptRegs.NMIFLG.bit.FLUNCERR << 1) | NmiIntruptRegs.NMIFLG.bit.RAMUNCERR;
    

    The OST flag is set once the serial communication starts. I have not yet found what causes that.

    Would it be possible for you to check what OST is being set? This can be checked through the TZOSTFLG register in order to determine if the OSHT 4 or 5 was set.

    Best Regards,

    Marlyn

  • Hi Marlyn,

    This is where I set DCBEVT1 and 2 are configured. This is just for PWM7 register. I do the same for PWM 8 and 9.

        PWM_Ph_A.DCTRIPSEL.bit.DCBHCOMPSEL   = 15;         // Trip combination input (all trip inputs selected by DCBHTRIPSEL register ORed together)
        PWM_Ph_A.DCBHTRIPSEL.bit.TRIPINPUT14 = 1;          // ECCDBLERR - This is enabled separately
    
        PWM_Ph_A.TZDCSEL.bit.DCBEVT1         = TZ_DCBH_HI; // 010: TZ_DCBH_HI = high, TZ_EVT_DISABLE, DCBL = don't care
        PWM_Ph_A.DCBCTL.bit.EVT1SRCSEL       = DC_EVT1;    // DCBEVT1 Source Signal Select, 0: Source Is DCBEVT1 Signal, 1: Source Is DCEVTFILT Signal
        PWM_Ph_A.DCBCTL.bit.EVT1FRCSYNCSEL   = 0;          // DCBEVT1 Force Synchronization Signal Select, 0: Source is passed through asynchronously, 1: Source is synchronized 
                                                           // with EPWMCLK
        PWM_Ph_A.TZDCSEL.bit.DCBEVT2         = TZ_DCBH_HI; // 010: DCBH = high, DCBL = don't care
        PWM_Ph_A.DCBCTL.bit.EVT2SRCSEL       = DC_EVT2;    // DCBEVT2 Source Signal Select, 0: Source Is DCBEVT2 Signal, 1: Source Is DCEVTFILT Signal
        PWM_Ph_A.DCBCTL.bit.EVT2FRCSYNCSEL   = 0;          // DCBEVT2 Force Synchronization Signal Select, 0: Source is passed through asynchronously, 1: Source is synchronized 
    

    Please give me a little bit of time to answer your next question.

    Thanks,

    Dhammika

  • Dhammika,

    I spoke with Marlyn on this some more yesterday and there is a relationship that exists between the ECC logic and the DC event as shown below:  Essentially there is a selection that allows an ECC error to be fed into the DC block, so that the ePWMs could be triggered/tripped if desired if there is an ECC event(either un-correctable or crossing the threshold set in the ECC for allowed correctable errors).

    To avoid the trip in your system would could disable this selection, but that is only solving the top level issue.  I think more concerning to me is that the system believes there has been an ECC event, even though the sta test didn't flag one during its testing.  I need to look into the ECC logic a bit more, I know that we store any failing address for further debug if these happen but  I also want to confirm the default settings for error thresholds, etc.

    I'll give another reply later today after I've researched a bit, in the meantime you could disable this as a trigger source into the DC block if you want to continue to debug you system. 

    I doubt that you have a real ECC event, BTW, but will need to track this back to the source a bit to understand how this could happen.

    Best,
    Matthew

  • Hi Matthew,

    Thanks for investigating this. We thought that trip-zone trigger for a bad ECC is more important than the self-test test on the ECC. So, currently we are keeping the power on self test disabled, and everyone is happy.

    Thanks,

    Dhammika

  • Dhammika,

    One thought I had, are you programming the flash with a bootloader or with CCS flash tool(or Uniflash)?  If you are using JTAG/IDE to program can you verify that you have "auto-ECC generation" option checked?  This FAQ goes into more detail on this, point #22 https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/951658/faq-faq-for-flash-ecc-usage-in-c2000-devices---includes-ecc-test-mode-linker-ecc-options?tisearch=e2e-sitesearch&keymatch=Flash%25252525252520ECC#

    If you are using the Flash with a bootloader, and using the Flash API I would also want to make sure we are programming the ECC as detailed in the above FAQ as well.

    Best,

    Matthew

  • Hi Matthew,

    I have the auto ECC generation checked. I use the CCS and the XDS110 debugger to program the chip.

    Thanks,

    Dhammika

  • Hi Matthew,

    Attached is the linker command file I use.

    Thanks,

    Dhammika

    //
    // Ensure STL_HWBIST_restoreContext() is linked properly.
    //
    -u _STL_HWBIST_restoreContext
    
    MEMORY
    {
    PAGE 0 :  /* Program Memory */
              /* Memory (RAM/FLASH) blocks can be moved to PAGE1 for data allocation */
              /* BEGIN is used for the "boot to Flash" bootloader mode   */
    
       HWBIST           : origin = 0x000000, length = 0x000020
       BEGIN           	: origin = 0x080000, length = 0x000002
       RAMM0            : origin = 0x000123, length = 0x0002DD
       RAMD0           	: origin = 0x00B000, length = 0x000800
       RAMLS0          	: origin = 0x008000, length = 0x000800
       RAMLS1          	: origin = 0x008800, length = 0x000800
       RAMLS2      		: origin = 0x009000, length = 0x000800
       RAMLS3      		: origin = 0x009800, length = 0x000800
       RAMLS4      		: origin = 0x00A000, length = 0x000800
       //RAMGS14          : origin = 0x01A000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
       //RAMGS15          : origin = 0x01B000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
       RESET           	: origin = 0x3FFFC0, length = 0x000002
       
       /* Flash sectors */
       FLASHA           : origin = 0x080002, length = 0x001FFE	/* on-chip Flash */
       FLASHB           : origin = 0x082000, length = 0x002000	/* on-chip Flash */
       FLASHC           : origin = 0x084000, length = 0x002000	/* on-chip Flash */
       FLASHD           : origin = 0x086000, length = 0x002000	/* on-chip Flash */
       FLASHE           : origin = 0x088000, length = 0x008000	/* on-chip Flash */
       FLASHF           : origin = 0x090000, length = 0x008000	/* on-chip Flash */
       FLASHG           : origin = 0x098000, length = 0x008000	/* on-chip Flash */
       FLASHH           : origin = 0x0A0000, length = 0x008000	/* on-chip Flash */
       FLASHI           : origin = 0x0A8000, length = 0x008000	/* on-chip Flash */
       FLASHJ           : origin = 0x0B0000, length = 0x008000	/* on-chip Flash */
       FLASHK           : origin = 0x0B8000, length = 0x002000	/* on-chip Flash */
       FLASHL           : origin = 0x0BA000, length = 0x002000	/* on-chip Flash */
       FLASHM           : origin = 0x0BC000, length = 0x002000	/* on-chip Flash */
       FLASHN           : origin = 0x0BE000, length = 0x001FF0	/* on-chip Flash */
    
    PAGE 1 : /* Data Memory */
             /* Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation */
    
       BOOT_RSVD       : origin = 0x000002, length = 0x000121     /* Part of M0, BOOT rom will use this for stack */
       RAMM1           : origin = 0x000400, length = 0x0003F8     /* on-chip RAM block M1. 7F8 to 400 should not be used */
       RAMD1           : origin = 0x00B800, length = 0x000800
    
       RAMLS5      : origin = 0x00A800, length = 0x0007A0
    
       RAMGS0      : origin = 0x00C000, length = 0x001000
       RAMGS1      : origin = 0x00D000, length = 0x001000
       RAMGS2      : origin = 0x00E000, length = 0x001000
       RAMGS3      : origin = 0x00F000, length = 0x001000
       RAMGS4      : origin = 0x010000, length = 0x001000
       RAMGS5_RAMGS6_RAMGS7      : origin = 0x011000, length = 0x003000
       RAMGS8_9    : origin = 0x014000, length = 0x002000
       RAMGS10_13  : origin = 0x016000, length = 0x004000
       
    }
    
    
    SECTIONS
    {
    // Section  Usage
    // .text    contains executable code
    // .data	contains initialized non-const data
    // .ebss 	reserves space for uninitialized variables (global variables)
    // .econst  used for initialized const objects
    // .cinit	used by C programs to initializing global variables at startup
    // .stack   used for the function call stack
    // .esysmem used for dynamic memory allocation pool (not used in UsbLanIf)
    // .pinit   used by C++ programs for global object constructors (not used in UsbLanIf)
    // .switch  jump tables for some switch statements
    // .cio     used for stdio function buffers (not used in UsbLanIf)
    //
    //  ADCDMA  small section used by DMA to store ADC values
    //
    // For any section that should be verified with a CRC, the linker command file must be modified to include
    // the crc_table() operator. The specification of a CRC algorithm is optional. The syntax is:
    // crc_table(user_specified_table_name[, algorithm=xxx])
    
       /* Allocate program areas: */
       .cinit              : > FLASHA      PAGE = 0, ALIGN(4), crc_table(_flash_crctbl, algorithm=CRC32_PRIME)
       .pinit              : > FLASHB,     PAGE = 0, ALIGN(4)       //This section will be empty since we don't have any C++ global constructors
       .text               : >> FLASHB | FLASHC | FLASHD | FLASHE | FLASHF, PAGE = 0, ALIGN(4), crc_table(_flash_crctbl, algorithm=CRC32_PRIME)
       codestart           : > BEGIN       PAGE = 0, ALIGN(4)
    
       /* Must be placed at 0x0000 */
       hwbist           : LOAD = FLASHJ,
                          RUN = HWBIST,
                          LOAD_START(_HwbistLoadStart),
                          LOAD_SIZE(_HwbistLoadSize),
                          LOAD_END(_HwbistLoadEnd),
                          RUN_START(_HwbistRunStart),
                          RUN_SIZE(_HwbistRunSize),
                          RUN_END(_HwbistRunEnd),
                          PAGE = 0, ALIGN(4)
    
       /* Must be placed lower than a 16-bit memory address */
       hwbiststack      : > RAMD0, START(_startOfHwbistStack), END(_endOfHwbistStack), SIZE(_sizeOfHwbistStack)      PAGE = 0
    
    #ifdef __TI_COMPILER_VERSION__
       #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc : {} LOAD = FLASHG,
                             RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_SIZE(_RamfuncsLoadSize),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
                             RUN_SIZE(_RamfuncsRunSize),
                             RUN_END(_RamfuncsRunEnd),
                             PAGE = 0, ALIGN(4), crc_table(_flash_crctbl, algorithm=CRC32_PRIME)
       #else
       ramfuncs            : LOAD = FLASHG,
                             RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_SIZE(_RamfuncsLoadSize),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
                             RUN_SIZE(_RamfuncsRunSize),
                             RUN_END(_RamfuncsRunEnd),
                             PAGE = 0, ALIGN(4), crc_table(_flash_crctbl, algorithm=CRC32_PRIME)
       #endif
    #endif
    						 
       /* Allocate uninitalized data sections: */
       .stack              : > RAMD1,
                               START(_startOfStack), END(_endOfStack), SIZE(_sizeOfStack)      PAGE = 1
       .ebss               : > RAMGS5_RAMGS6_RAMGS7
                               START(_startOfEbss), END(_endOfEbss), SIZE(_sizeOfEbss)         PAGE = 1
       .esysmem            : > RAMLS5       PAGE = 1
    
       /* Initalized sections go in Flash */
       .econst             : >> FLASHH | FLASHI,  PAGE = 0, ALIGN(4), crc_table(_flash_crctbl, algorithm=CRC32_PRIME)
       .switch             : > FLASHG,            PAGE = 0, ALIGN(4)
       
       /* Sections for STL_RAM tests */
       m1ram            : > RAMM1,      PAGE = 1
       ls5ram           : > RAMLS5,     PAGE = 1
    
       //Space for the RAM copy of the contents of EEPROM
       //and the space for copying ram during memory checks
       UNION
       {
       	RamSaveArea		:
       } > RAMGS10_13
         START(_RamSaveStart), SIZE(_RamSaveSize), END(_RamSaveEnd),
         PAGE = 1, ALIGN(4)
    
       .reset              : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */
    
    	//Section to hold the flash_crctbl
    	//Note that we can not generate a crc_table entry for this section.
    	.TI.crctab			: > FLASHK, PAGE = 0
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    

  • Dhammika,

    Matt is out of office today. He will come back to office on Monday, so please response by Monday/Tuesday.

    Thanks & Regards,

    Santosh

  • Dhammika,

    Let's see if we can root down to the address(or something else!) that is causing the ECC trip event to occur.

    We're going to look a the MemoryErrorRegs at base address 0x5F500.  I want to look at both the uncorrectable and correctable flag and flag set registers as detailed below:

    UCERRFLG

    UCERRSET

    CERRFLG

    CERRSET

    If we see the any bit set in either of the FLG registers, we can use the associated address to determine where the error occurred and go from there.

    If we see any bit set in the "SET" registers, then this is an indication that the interrupt was forced(perhaps to check functionality), and would need to be cleared before we activate the path to the trip zone.  In fact while I'm writing this, I'm wondering if that is what is happening, i.e. the ECC STA tests have an intentional activation of the logic to make sure it works.  We should be clearing this out before we pass control back to main, however, so let's see what your investigation uncovers.

    Best,

    Matthew

  • Hi Matthew,

    Immediately after the power on self-test is performed, these are the values in those memory registers. 

    UCERRFLG	    0x00000000	Uncorrectable Error Flag Register [Memory Mapped]
    UCERRSET	    0x00000000	Uncorrectable Error Flag Set Register [Memory Mapped]
    UCERRCLR	    0x00000000	Uncorrectable Error Flag Clear Register [Memory Mapped]
    UCCPUREADDR	    0x0000A800	Uncorrectable CPU Read Error Address [Memory Mapped]
    UCDMAREADDR	    0x00000000	Uncorrectable DMA Read Error Address [Memory Mapped]
    UCCLA1READDR	0x00000000	Uncorrectable CLA1 Read Error Address [Memory Mapped]
    CERRFLG    	    0x00000000	Correctable Error Flag Register [Memory Mapped]
    CERRSET	        0x00000000	Correctable Error Flag Set Register [Memory Mapped]
    CERRCLR	        0x00000000	Correctable Error Flag Clear Register [Memory Mapped]
    CCPUREADDR	    0x00000400	Correctable CPU Read Error Address [Memory Mapped]
    CERRCNT	        0x00000000	Correctable Error Count Register [Memory Mapped]
    CERRTHRES       0x00000001	Correctable Error Threshold Value Register [Memory Mapped]
    CEINTFLG	    0x00000000	Correctable Error Interrupt Flag Status Register [Memory Mapped]
    CEINTCLR	    0x00000000	Correctable Error Interrupt Flag Clear Register [Memory Mapped]
    CEINTSET	    0x00000000	Correctable Error Interrupt Flag Set Register [Memory Mapped]
    CEINTEN	        0x00000001	Correctable Error Interrupt Enable Register [Memory Mapped]
    

    Those values remain the same even up to the point where motor control ISR is enabled. 

    Thanks,

    Dhammika

  • Dhammika,

    The addresses listed are in LS5 RAM (A800) and M1 RAM(0x400).  I noticed in your linker that these are being used as follows:

    /* Sections for STL_RAM tests */
    m1ram : > RAMM1, PAGE = 1
    ls5ram : > RAMLS5, PAGE = 1

    I think that these may have some error injection intentionally as part of the ram tests.  Can you look back in your code, and after the RAM STL test patterns run, intentionally re-init those RAMs with all 0x0000 data before proceeding.  I'm thinking there is still some leftover bad data in there post the stl tests.

    Best,

    Matthew

  • Hi Matthew,

    I tried this but even that did not work. I still have DCBEVT1 and DCBEVT2 set immediately after motor control ISR is enabled. 

    Thanks,

    Dhammika

  • Dhammika,

    Let me loop in some more folks, now that we have the addresses that are causing the issue we should be able to root cause this.

    Best,

    Matthew

  • Dhammika,

    I spoke with some others, and from the linker file the RAMs that are allocated for the STA tests will have some errors forced into them to check the state of the logic.  That would explain why we see those addresses in the status registers.  What is not clear is that in the snapshot you took the error flags have already been cleared, this should have prevented the TZ from seeing that they were set inside the STA tests, or at least we want them cleared before we jump back to main.

    In your code can you add code to ensure these are clear before you enable the TZ path for the RAM errors?  There are 2 functions in memcfg.h to do this:

    MemCfg_clearCorrErrorStatus()  and MemCfg_clearUncorrErrorStatus()   you can pass flag parameter MEMCFG_CERR_CPUREAD and MEMCFG_UCERR_CPUREAD respectively.

    Again, I would think the STA tests would clear these before passing control back to "main", but trying to see exactly where we are going wrong in the process of coming out of the test mode.

    Best,

    Matthew

  • Hi Matthew,

    I tried this by executing those routines after the RAM test ends. I put them at the end of that routine. The DCBEVT1 and DCBEVT2 are still set immediately after motor control ISR is enabled.

    Thanks,

    Dhammika

  • Are you able to clear the trip zone flag and run your motor control as normal? Or is this condition sticking around even after you've cleared the related MemCfg and TZ error flags?

    Do you configure the EPWMs before your memory test? It's not clear to me how the ECCDBLERR signal could propagate to the TZ if you don't configure digital compare and trip zone modules until after the POST tests have run and you've cleared the error flags.

    Whitney

  • Also, I believe this signal is for both Flash and RAM errors, so check the Flash0EccRegs flags too.

    Whitney

  • Hi Whitney,

    It seems you cannot see a reason for this issue. I think I have to be happy with the current configuration I have - which is disabling the flash ECC test and keeping all the trip-zone triggers active. 

    Thanks,

    Dhammika

  • Hi Dhammika,

    I'll try to see if I can reproduce this issue this week since I'd like to try to get to the bottom of what's happening. I'll let you know how it goes.

    Whitney

  • I gave it a try. Basically a set up a PWM that could be tripped by ECCDBLERR, and then ran some tests where I injected error into RAM and Flash. If I ran the tests before initializing the PWMs, as long as I cleared all the error flags in MemoryErrorRegs and Flash0EccRegs, before I initialized the PWMs (thus establishing the path from ECCDBLERR to the TZ logic), the PWM didn't trip immediately on my enabling it.

    If I ran the tests after I had already initialized the PWMs (ECCDBLERR connected to the TZ logic at the start), I did see the trip happen when I ran the RAM and Flash tests. All I had to do to restore functionality though was to clear all the error flags in MemoryErrorRegs and Flash0EccRegs and then clear the TZ flags in the PWM registers--

         EPWM_clearTripZoneFlag(EPWM1_BASE,
                                (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST | EPWM_TZ_FLAG_DCAEVT1));
         EPWM_clearOneShotTripZoneFlag(EPWM1_BASE, EPWM_TZ_OST_FLAG_DCAEVT1);

    Actual flags may vary depending on how you've configured the PWM, but this is what I used.

    Not sure if that will provide any insights into what may be happening in your application or ideas of things to investigate. If you're fine with your current workaround anyway, we can close the thread.

    Whitney

  • Hi Whitney,

    Thanks for trying this. One difference between your scenario and my one is the enabling of the ADC_PPB trip zones. In my case, the trip zone flags associated with ADDC_PPB + over current are set when the Flash ECC power on self test is done at the beginning. I tried to clear these flags before motor control ISR is enabled. They do not go away. That means inputs to the digital filter or the comparator still remains set.

    Thanks,

    Dhammika 

  • You see the ADCEVTSTAT bits are getting set? ADCEVTCLR doesn't work to clear the condition?

    Whitney

  • Hi Whitney,

    I missed that flag. However, I modified the code so that I clear that flag just after POSTs, just before enabling motor control ISR etc. That did not make any difference. Just before enabling the motor control ISR, ADCEVTSTAT was clear. However, the CBC flag in PWM  TZFLG register was set. Then immediately after motor control ISR is enabled, trip Hi flags in ADCEVTSTAT becomes high and DCBEVT1 and DCBEVT2 flags in TZFLG register are set. 

    Thanks,

    Dhammika

  • However, the CBC flag in PWM  TZFLG register was set.

    And what is the value of TZCBCFLG at that point? Which trip source was still active?

    Then immediately after motor control ISR is enabled, trip Hi flags in ADCEVTSTAT becomes high and DCBEVT1 and DCBEVT2 flags in TZFLG

    Do you know if there was an actual ADCEVT at that point? Did the ADC result actually cross the boundary?

    The Flash0EccRegs flags are all still 0 at that point? Only the DCBEVT1/2 TZ flags are set? I thought the ADC PPB events were tied to the DCAEVTs? Just to make sure I've read your configuration right--

    • DCA-->TRIP4 (CMPSS trip signals) OR TRIP5 (ADC PPB limit events)
    • DCB-->ECCDBLERR (and no others?)
    • And then TZ4, TZ5, and TZ6 are also enabled, yes?

    Whitney

  • Hi Whitney,

    Sorry for taking so long to reply. I am involved in another project and I had to come up to speed on that quickly. Here are the responses to your questions. I think we should temporarily stop this thread until I come back to this project again. However, I would like to get this solved at some point. Thank you very much for being so patient with me.

    My answers are highlighted in yellow. 

    Note: The point in question here is “Immediately after motor control ISR is enabled, trip Hi flags in ADCEVTSTAT becomes high and DCBEVT1 and DCBEVT2 flags in TZFLG registers are set”.

    And what is the value of TZCBCFLG at that point? Which trip source was still active?

    <It seems CBC6 flag is the one that is set. So, I changed ...TZSEL.bit.CBC6 bits on all three PWM channels to 0. Technically, this should be set to 1. In fact, this whole system used to work when the program was not as big as now. I kept the trip-zone disabled since some people mistakenly thought the problems, they had been due to the trip-zone.>

    Do you know if there was an actual ADCEVT at that point? Did the ADC result actually cross the boundary?

    <The current is 0 at this point. The ADCPPB trip zone is activated only after the ADC offset is written to ADC PPB OFFSET REF registers. I cannot even clear the ADCEVTSTAT after they are set. This means internally the trigger condition still persist, and I do not know why>

    The Flash0EccRegs flags are all still 0 at that point? Only the DCBEVT1/2 TZ flags are set? I thought the ADC PPB events were tied to the DCAEVTs? Just to make sure I've read your configuration right--

    <Flash0EccRegs have flags set indicating even uncorrectable errors have occurred. ADC PPB events were tied to the DCAEVTs - that is correct.>

     

    DCA-->TRIP4 (CMPSS trip signals) OR TRIP5 (ADC PPB limit events) - YES

    DCB-->ECCDBLERR (and no others?) - YES

    And then TZ4, TZ5, and TZ6 are also enabled, yes? YES

    Thanks,

    Dhammika

  • Hi Dhammika,

    Thanks for the additional details. No problem about pausing the thread for a bit. I'll try to come up with some more ideas of what could be causing this in the meantime, and we'll pick it up again when you have the time.

    Whitney