Example #1
0
/**
* Inject errors using the hardware fault injection functionality, and write
* random data and read it back using the indicated location.
*
* @param	InstancePtr is a pointer to the XBram instance to
*		be worked on.
* @param	The Addr is the indicated memory location to use
* @param	The Index1 is the bit location of the first injected error
* @param	The Index2 is the bit location of the second injected error
* @param	The ActualData is filled in with expected data for checking
* @param	The ActualEcc is filled in with expected ECC for checking
*
* @return 	None
*
* @note		None.
*
******************************************************************************/
static void InjectErrors(XBram * InstancePtr, u32 Addr,
                         int Index1, int Index2,
                         u32 *ActualData, u32 *ActualEcc)
{
    u32 InjectedData = 0;
    u32 InjectedEcc = 0;
    u32 RandomData = PrngData(&PrngResult);

    if (Index1 < 32) {
        InjectedData = 1 << Index1;
    } else {
        InjectedEcc = 1 << (Index1 - 32);
    }

    if (Index2 < 32) {
        InjectedData |= (1 << Index2);
    } else {
        InjectedEcc |= 1 << (Index2 - 32);
    }

    WR(FI_D_0_OFFSET, InjectedData);
    WR(FI_ECC_0_OFFSET, InjectedEcc);

    XBram_Out32(Addr, RandomData);
    (void) XBram_In32(Addr);

    *ActualData = InjectedData ^ RandomData;
    *ActualEcc  = InjectedEcc ^ CalculateEcc(RandomData);
}
Example #2
0
/**
*
* This function ensures that ECC in the BRAM is initialized if no hardware
* initialization is available. The ECC bits are initialized by reading and
* writing data in the memory. This code is not optimized to only read data
* in initialized sections of the BRAM.
*
* @param	ConfigPtr is a reference to a structure containing information
*		about a specific BRAM device.
* @param 	EffectiveAddr is the device base address in the virtual memory
*		address space.
*
* @return
*		None
*
* @note		None.
*
*****************************************************************************/
void InitializeECC(XBram_Config *ConfigPtr, u32 EffectiveAddr)
{
	u32 Addr;
	volatile u32 Data;

	if (ConfigPtr->EccPresent &&
	    ConfigPtr->EccOnOffRegister &&
	    ConfigPtr->EccOnOffResetValue == 0 &&
	    ConfigPtr->WriteAccess != 0) {
		for (Addr = ConfigPtr->MemBaseAddress;
		     Addr < ConfigPtr->MemHighAddress; Addr+=4) {
			Data = XBram_In32(Addr);
			XBram_Out32(Addr, Data);
		}
		XBram_WriteReg(EffectiveAddr, XBRAM_ECC_ON_OFF_OFFSET, 1);
	}
}
Example #3
0
/**
* Inject errors using the hardware fault injection functionality, and write
* random data and read it back using the indicated location.
*
* @param	InstancePtr is a pointer to the XBram instance to
*		be worked on.
* @param	The Addr is the indicated memory location to use
* @param	The Index1 is the bit location of the first injected error
* @param	The Index2 is the bit location of the second injected error
* @param	The Width is the data byte width
* @param	The ActualData is filled in with expected data for checking
* @param	The ActualEcc is filled in with expected ECC for checking
*
* @return 	None
*
* @note		None.
*
******************************************************************************/
static void InjectErrors(XBram * InstancePtr, u32 Addr,
			 int Index1, int Index2, int Width,
			 u32 *ActualData, u32 *ActualEcc)
{
	u32 InjectedData = 0;
	u32 InjectedEcc = 0;
	u32 RandomData = PrngData(&PrngResult);

	if (Index1 < 32) {
		InjectedData = 1 << Index1;
	} else {
		InjectedEcc = 1 << (Index1 - 32);
	}

	if (Index2 < 32) {
		InjectedData |= (1 << Index2);
	} else {
		InjectedEcc |= 1 << (Index2 - 32);
	}

	WR(FI_D_0_OFFSET, InjectedData);
	WR(FI_ECC_0_OFFSET, InjectedEcc);

	XBram_Out32(Addr, RandomData);
	Xil_DCacheFlushRange(Addr, 4);
	switch (Width) {
		case 1: /* Byte - Write to do Read-Modify-Write */
			XBram_Out8(Addr, PrngData(&PrngResult) & 0xFF);
			break;
		case 2: /* Halfword - Write to do Read-Modify-Write */
			XBram_Out16(Addr, PrngData(&PrngResult) & 0xFFFF);
			break;
		case 4:	/* Word - Read */
			(void) XBram_In32(Addr);
			break;
	}
	*ActualData = InjectedData ^ RandomData;
	*ActualEcc  = InjectedEcc ^ CalculateEcc(RandomData);
}
Example #4
0
/**
* Run a self-test on the driver/device. Unless fault injection is implemented
* in hardware, this function only does a minimal test in which available
* registers (if any) are written and read.
*
* With fault injection, all possible single-bit and double-bit errors are
* injected, and checked to the extent possible, given the implemented hardware.
*
* @param	InstancePtr is a pointer to the XBram instance.
*
* @return 	XST_SUCCESS unless fault injection is implemented and an
*		injected fault is not correctly detected.
*
*		If the BRAM device is not present in the
*		hardware a bus error could be generated. Other indicators of a
*		bus error, such as registers in bridges or buses, may be
*		necessary to determine if this function caused a bus error.
*
* @note		None.
*
******************************************************************************/
int XBram_SelfTest(XBram *InstancePtr)
{
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    if (InstancePtr->Config.CtrlBaseAddress == 0)
        return (XST_SUCCESS);

    /*
     * Only 32-bit data width is supported as of yet. 64-bit and 128-bit
     * widths will be supported in future.
     */
    if (InstancePtr->Config.DataWidth != 32)
        return (XST_SUCCESS);

    /*
     * Read from the implemented readable registers in the hardware device.
     */
    if (InstancePtr->Config.CorrectableFailingRegisters) {
        (void) RD(CE_FFA_0_OFFSET);
        (void) RD(CE_FFD_0_OFFSET);
        (void) RD(CE_FFE_0_OFFSET);
    }
    if (InstancePtr->Config.UncorrectableFailingRegisters) {
        (void) RD(UE_FFA_0_OFFSET);
        (void) RD(UE_FFD_0_OFFSET);
        (void) RD(UE_FFE_0_OFFSET);
    }

    /*
     * Write and read the implemented read/write registers in the hardware
     * device.
     */
    if (InstancePtr->Config.EccStatusInterruptPresent) {

        WR(ECC_EN_IRQ_OFFSET, 0);
        if (RD(ECC_EN_IRQ_OFFSET) != 0) {
            return (XST_FAILURE);
        }
    }

    if (InstancePtr->Config.CorrectableCounterBits > 0) {
        u32 Value;

        /* Calculate counter max value */
        if (InstancePtr->Config.CorrectableCounterBits == 32) {
            Value = 0xFFFFFFFF;
        } else {
            Value = (1 <<
                     InstancePtr->Config.CorrectableCounterBits) - 1;
        }

        WR(CE_CNT_OFFSET, 0xFFFFFFFF);
        if (RD(CE_CNT_OFFSET) != Value) {
            return (XST_FAILURE);
        }

        WR(CE_CNT_OFFSET, 0);
        if (RD(CE_CNT_OFFSET) != 0) {
            return (XST_FAILURE);
        }
    }

    /*
     * If fault injection is implemented, inject all possible single-bit
     * and double-bit errors, and check all observable effects.
     */
    if (InstancePtr->Config.FaultInjectionPresent &&
            InstancePtr->Config.WriteAccess != 0) {

        const u32 Addr[2] = {InstancePtr->Config.MemBaseAddress &
                             0xfffffffc,
                             InstancePtr->Config.MemHighAddress &
                             0xfffffffc
                            };
        u32 SavedWords[2];
        u32 ActualData;
        u32 ActualEcc;
        u32 CounterValue;
        u32 CounterMax;
        int WordIndex = 0;
        int Result = XST_SUCCESS;
        int Index1;
        int Index2;

        PrngResult = 42; /* Random seed */

        /* Save two words in BRAM used for test */
        SavedWords[0] = XBram_In32(Addr[0]);
        SavedWords[1] = XBram_In32(Addr[1]);

        /* Calculate counter max value */
        if (InstancePtr->Config.CorrectableCounterBits == 32) {
            CounterMax = 0xFFFFFFFF;
        } else {
            CounterMax =(1 <<
                         InstancePtr->Config.CorrectableCounterBits) - 1;
        }

        /* Inject and check all single bit errors */
        for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) {
            /* Save counter value */
            if (InstancePtr->Config.CorrectableCounterBits > 0) {
                CounterValue = RD(CE_CNT_OFFSET);
            }

            /* Inject single bit error */
            InjectErrors(InstancePtr, Addr[WordIndex], Index1,
                         Index1, &ActualData, &ActualEcc);

            /* Check that CE is set */
            if (InstancePtr->Config.EccStatusInterruptPresent) {
                CHECK(ECC_STATUS_OFFSET,
                      XBRAM_IR_CE_MASK, Result);
            }

            /* Check that address, data, ECC are correct */
            if (InstancePtr->Config.CorrectableFailingRegisters) {
                CHECK(CE_FFA_0_OFFSET, Addr[WordIndex], Result);
#if 0
                /*
                 * The following 2 registers are not implemented
                 * in the current version of the axi_bram_ctrl.
                 * This is a common driver for axi_bram_ctrl and
                 * lmb_bram_if_cntlr.
                 */
                CHECK(CE_FFD_0_OFFSET, ActualData, Result);
                CHECK(CE_FFE_0_OFFSET, ActualEcc, Result);
#endif
            }

            /* Check that counter has incremented */
            if (InstancePtr->Config.CorrectableCounterBits > 0 &&
                    CounterValue < CounterMax) {
                CHECK(CE_CNT_OFFSET,
                      CounterValue + 1, Result);
            }

            /* Restore correct data in the used word */
            XBram_Out32(Addr[WordIndex], SavedWords[WordIndex]);

            /* Clear status register */
            if (InstancePtr->Config.EccStatusInterruptPresent) {
                WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK);
            }

            /* Switch to the other word */
            WordIndex = WordIndex ^ 1;

            if (Result != XST_SUCCESS) break;

        }

        if (Result != XST_SUCCESS) {
            return XST_FAILURE;
        }

        for (Index1 = 0; Index1 < TOTAL_BITS; Index1++) {
            for (Index2 = 0; Index2 < TOTAL_BITS; Index2++) {
                if (Index1 != Index2) {
                    /* Inject double bit error */
                    InjectErrors(InstancePtr,
                                 Addr[WordIndex],
                                 Index1, Index2,
                                 &ActualData,
                                 &ActualEcc);

                    /* Check that UE is set */
                    if (InstancePtr->Config.
                            EccStatusInterruptPresent) {
                        CHECK(ECC_STATUS_OFFSET,
                              XBRAM_IR_UE_MASK,
                              Result);
                    }

                    /* Check that address, data, ECC are correct */
                    if (InstancePtr->Config.
                            UncorrectableFailingRegisters) {
                        CHECK(UE_FFA_0_OFFSET, Addr[WordIndex],
                              Result);
                        CHECK(UE_FFD_0_OFFSET,
                              ActualData, Result);
                        CHECK(UE_FFE_0_OFFSET, ActualEcc,
                              Result);
                    }

                    /* Restore correct data in the used word */
                    XBram_Out32(Addr[WordIndex],
                                SavedWords[WordIndex]);

                    /* Clear status register */
                    if (InstancePtr->Config.
                            EccStatusInterruptPresent) {
                        WR(ECC_STATUS_OFFSET,
                           XBRAM_IR_ALL_MASK);
                    }

                    /* Switch to the other word */
                    WordIndex = WordIndex ^ 1;
                }
                if (Result != XST_SUCCESS) break;
            }
            if (Result != XST_SUCCESS) break;
        }

        /* Check saturation of correctable error counter */
        if (InstancePtr->Config.CorrectableCounterBits > 0 &&
                Result == XST_SUCCESS) {

            WR(CE_CNT_OFFSET, CounterMax);

            InjectErrors(InstancePtr, Addr[WordIndex], 0, 0,
                         &ActualData, &ActualEcc);

            CHECK(CE_CNT_OFFSET, CounterMax, Result);
        }

        /* Restore the two words used for test */
        XBram_Out32(Addr[0], SavedWords[0]);
        XBram_Out32(Addr[1], SavedWords[1]);

        /* Clear the Status Register. */
        if (InstancePtr->Config.EccStatusInterruptPresent) {
            WR(ECC_STATUS_OFFSET, XBRAM_IR_ALL_MASK);
        }

        /* Set Correctable Counter to zero */
        if (InstancePtr->Config.CorrectableCounterBits > 0) {
            WR(CE_CNT_OFFSET, 0);
        }

        return (Result);
    }

    return (XST_SUCCESS);
}