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.

Getting flash ECC interrupt to fire (F2837xD)

Other Parts Discussed in Thread: CONTROLSUITE

I'm working with internal flash on the F28377D based controlCARD starting with the flash_programming_cpu01 project. I would like to provoke single and double bit ECC errors to confirm that my code detects these events through the associated interrupt.

I found a very helpful post at  and am trying to incorporate that into the project. It's not related to the project itself but at least I know that the code in the project does work with the flash API so that makes a good starting point.

I have the following code

EALLOW;	// This is needed to write to EALLOW protected registers
	if(type == 1) {
		Flash0EccRegs.ERR_INTCLR.all = 3;			// clear SINGLE_ERR_INTCLR and UNC_ERR_INTCLR
		Flash0EccRegs.ERR_INTCLR.bit.SINGLE_ERR_INTCLR = 1;
		PieVectTable.FLASH_CORRECTABLE_ERROR_INT = &test_Single_ECC_isr;
		PieCtrlRegs.PIEIER12.bit.INTx11 = 1; 	//C28FLSINGERR
		IER = 0x800; // Enable CPU INT
		ERTM;
		EINT;
		EDIS;
		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
		return;
	}

The Flash0EccRegs configure according to the code and the first read from 0x701F8 sets both error flags in the ERR_INTFLAG register. IER.INT12 is set. IFR.INT12 is also set. PIEIER12.INTx11 (Int 12.11) is set.
I suppose the problem is that the interrupt seems not to be propagating from the ECC module to the interrupt controller. STM.INTM is 0 as is STM.DBGM.

What have I overlooked that is causing the ISR to not be called? (Both the code above and the ISR reside in RAM.)

  • Last line should not be in the code section, for readability I'm copying it here:

    The Flash0EccRegs configure according to the code and the first read from 0x701F8 sets both error flags in the ERR_INTFLAG register. IER.INT12 is set. IFR.INT12 is also set. PIEIER12.INTx11 (Int 12.11) is set.I suppose the problem is that the interrupt seems not to be propagating from the ECC module to the interrupt controller. STM.INTM is 0 as is STM.DBGM.What have I overlooked that is causing the ISR to not be called? (Both the code above and the ISR reside in RAM.)
  • Hi Hank,

    First comment is, be careful to put the EDIS in the if condition. It may not be executed to close the EALLOW.

    What is the error count threshold you set for single bit errors?

    It seems you have configured everything correctly. I would make sure the PIE is acknowledge before enabling the interrupt and reading the error.
    Set up the interrupt in this order:

    1. Disable interrupt
    2. Clear status flags
    3. Register ISR vector
    4. Clear PIE11
    5. Enable interrupt

    Also, I am not 100% positive the single bit error interrupt will be taken in this case because there is also an uncorrectable bit error happening when you read 0x701F8. In this case both the correctable and uncorrectable bit errors are triggered and an NMI will be triggered.

    Both may fire, or just the NMI will fire I am not sure exactly.

    I would test this with the Flash Wrapper Test Registers. You can use the test registers to ensure that the interrupt is being forced with you input a correctable bit error into the test registers.

    sal
  • Hi Sal,

    Thanks for the reply and suggestions. I will look into them momentarily. In the mean time I have made some progress. I added a second state with code intended to provoke the NMI due to multiple bit errors.

    	EALLOW;	// This is needed to write to EALLOW protected registers
    	// install both vectors
    	PieVectTable.FLASH_CORRECTABLE_ERROR_INT = &test_Single_ECC_isr;
    	PieVectTable.NMI_INT = &test_Double_ECC_isr;
    	if(type == 1) {
    		Flash0EccRegs.ERR_INTCLR.all = 3;			// clear SINGLE_ERR_INTCLR and UNC_ERR_INTCLR
    		Flash0EccRegs.ERR_INTCLR.bit.SINGLE_ERR_INTCLR = 1;
    		PieCtrlRegs.PIEIER12.bit.INTx11 = 1; 	//C28FLSINGERR
    		IER = 0x800; // Enable CPU INT
    		ERTM;
    		EINT;
    		EDIS;
    		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
    
    		return;
    	}
    	else if(type == 2) {
    		Flash0EccRegs.ERR_INTCLR.all = 3;			// clear SINGLE_ERR_INTCLR and UNC_ERR_INTCLR
    		Flash0EccRegs.ERR_INTCLR.bit.SINGLE_ERR_INTCLR = 1;
    		PieCtrlRegs.PIEIER12.bit.INTx11 = 1; 	//C28FLSINGERR
    		IER = 0x800; // Enable CPU INT
    		NmiIntruptRegs.NMIFLGCLR.all = 0xFFFF;
    		ERTM;
    		EINT;
    		EDIS;
    		readVal = *(uint16*)0x701F8; 	// provoke both single and double bit ECC error
    
    		return;
    	}
    

    By mistake the first cut included code to enable the single bit interrupt and I found that it was firing (for case 2.) I also discovered that if I single step through the code, the interrupt does not fire. 

    thanks,

    hank

  • Hi Sal,

    To answer your comments...

     be careful to put the EDIS in the if condition. It may not be executed to close the EALLOW

    I take your point but it is not an issue for this code as it is not intended to be a part of a running system. It either takes the ISR or does not and in all cases hits an ESTOP0 instruction so the path can be determined in the debugger. I also determined that provoking the interrupt and immediately executing the ESTOP0 instruction did not allow time for the ISR to execute. 

    What is the error count threshold you set for single bit errors?

    I set that to zero so it interrupts on the first single bit error.

    Also, I am not 100% positive the single bit error interrupt will be taken in this case ...

    If the NMI is not enabled, the single bit interrupt fires and the ISR executes. In the code listed below that is the situation for "type == 1." If I execute the "type == 2" section, the NMI is enabled and the NMI interrupt fires and ISR executes. If I restart the program (without reloading the program) and repeat the "type==1" section, the NMI remains enabled and the NMI interrupt fires. Apparently restarting the program does not reset the processor. Further, the following instruction does not clear the NMIE bit.

    	    NmiIntruptRegs.NMICFG.bit.NMIE = 0x0;	// disable NMI
    

    At this point this is not a big concern because I don't think that our application will be switching the NMIE enable back and forth but I would like to understand why it does not happen. Perhaps it is a result of mismatched EALLOW/EDIS which you mentioned earlier.

    Here is the code snippet that (mostly) performs as expected

    	EALLOW;	// This is needed to write to EALLOW protected registers
    	// clear NMI interrupt
    	if((NmiIntruptRegs.NMIFLG.bit.NMIINT == 1) && (NmiIntruptRegs.NMIFLG.bit.FLUNCERR == 1))
    	{
    		NmiIntruptRegs.NMIFLGCLR.bit.FLUNCERR = 0x1;
    		NmiIntruptRegs.NMIFLGCLR.bit.NMIINT = 0x1;
    	}
    	Flash0EccRegs.ERR_INTCLR.all = 3;			// clear SINGLE_ERR_INTCLR and UNC_ERR_INTCLR
    
    	// install both vectors
    	PieVectTable.FLASH_CORRECTABLE_ERROR_INT = &test_Single_ECC_isr;
    	PieVectTable.NMI_INT = &test_Double_ECC_isr;
    	if(type == 1) {		// single bit error ISR configuired, trigger with read from 0x701F8
    	    PieCtrlRegs.PIEIER12.bit.INTx11 = 1;    //C28FLSINGERR
    	    NmiIntruptRegs.NMIFLGCLR.all = 0xFFFF;	// clear all pending NMI
    	    NmiIntruptRegs.NMICFG.bit.NMIE = 0x0;	// disable NMI
    	    IER = 0x800; // Enable CPU INT12
    	    ERTM;
    	    EINT;
    	    EDIS;
    	    readVal = *(uint16*)0x701F8;    // provoke both single and double bit ECC error
    	    __asm(" RPT #7 || NOP");
    	    ESTOP0;	// stop - no interrupt
    	    return;
    	}
    	else if(type == 2) {
    	    NmiIntruptRegs.NMIFLGCLR.all = 0xFFFF;
    	    ERTM;
    	    EINT;
    	    NmiIntruptRegs.NMICFG.bit.NMIE = 0x1;
    	    EDIS;
    	    readVal = *(uint16*)0x701F8;    // provoke both single and double bit ECC error
    	    __asm(" RPT #7 || NOP");
    	    ESTOP0;	// stop - no interrupt
    	    return;
    	}
    

    thanks,

    hank

  • Hi Sal,

    I replied to your post in the other thread but for reasons not obvious to me the post appeared as the start of a new thread rather than a reply. Please see the post at 

    If the forum admin can move the post to this thread where it belongs, that would be much appreciated.

    thanks,

    hank

  • Hank, Sal,

    I've merged the threads to this post.
    To clarify, I moved over the post that started with "Hi Sal, To answer your comments..."

    Elizabeth
  • Hi Hank,

    On following query -

    Apparently restarting the program does not reset the processor. Further, the following instruction does not clear the NMIE bit.
    1
    NmiIntruptRegs.NMICFG.bit.NMIE = 0x0;   // disable NMI

    At this point this is not a big concern because I don't think that our application will be switching the NMIE enable back and forth but I would like to understand why it does not happen. Perhaps it is a result of mismatched EALLOW/EDIS which you mentioned earlier.

    Here is the code snippet that (mostly) performs as expected

    Please note that this register bit type is R/W=1 (Table 2-57. NMICFG Register Field Descriptions) which means it can be only set to '1' but not '0' hence the code you have is not working.

    Sal will respond to your other queries.

    Regards,

    Vivek Singh

  • Hi Vivek,
    Thanks for pointing that out. I guess the implication is that once the NMIE is enabled it cannot be disabled.

    best,
    hank
  • Hank,

    Once NMI is enabled, it cannot be disabled except by a SYSRSn.

    It seems like the ISR and NMI are being triggered and serviced as expected now.

    Is there any other particular question or issue you are having?

    Regards,
    sal

  • Hi Sal,
    Thank you for your help. The only other issue I've encountered (this morning ;) ) is the documentation for Fapi_issueProgrammingCommand() in spnu501d.pdf. It seems like it assumes 8 bit bytes and that's not true of the Delfino. I was able to work through that by issuing calls and watching to see what was modified in the flash address space but it would be helpful to have the documentation updated. I'm guessing it was written for ARM based chips which do have 8 bit bytes.

    thanks again,
    hank
  • I will notify our flash expert. Thank you!

    sal
  • Hank,

    SPNU501D.pdf is Flash API documentation for TMS570 devices.
    For C2000, please find API documentation at C:\ti\controlSUITE\device_support\F2837xD\vx\doc\FlashAPI_Doc.

    In SPNU595, we mention the Fapi_issueProgrammingCommand() for both ARM and C28x cores. Please check section 3.4.1.2 in SPNU595 and it mentions that the data buffer length for C28x is expected in number of 16-bit words.

    Thanks and best regards,
    Vamsi
  • Hi Vamsi,

    Thanks for the info. Perhaps the next time TI updates SPNU501D.pdf they could update the statement

    This reference guide provides a detailed description of Texas Instruments' F021 Flash API functions that
    can be used to erase, program and verify F021 Flash on TI devices.

    to specify which devices it applies to. I was confused by the versions and thought that 

    C2000 F021 Flash API
    Version 1.53
    Reference Guide

    was an older version of

    F021 Flash API
    Version 2.00.00
    Reference Guide

    best,

    hank

  • Hank,

    Sure, I will pass this feedback to TMS570 team now.

    Thanks and regards,
    Vamsi