📄 ixparityenacccodelet.c
字号:
if (NULL == memAddr4ECCErrorInjection) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletECCErrorInject: Failed to allocate memory for ECC error injection\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletECCErrorInject: inject ECC error at %08x, multiBit %d injectNow %d\n", (UINT32)memAddr4ECCErrorInjection, multiBit, injectNow, 0, 0, 0); /* initialize the value */ IX_OSAL_WRITE_LONG (memAddr4ECCErrorInjection, 0); ixParityENAccCodeletMcuRegBaseAddr = (UINT32) IX_OSAL_MEM_MAP (IX_OSAL_IXP400_PARITYEN_PHYS_BASE, IX_OSAL_IXP400_PARITYEN_MAP_SIZE); if (0 == ixParityENAccCodeletMcuRegBaseAddr) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletECCErrorInject: Failed to get ECC Register Base Address\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } tstECCRegAddr = (UINT32 *) (ixParityENAccCodeletMcuRegBaseAddr + IX_PARITYENACC_CODELET_ECC_TEST_REG_OFFSET); /* configure ECC Test Register to generate single bit bad ECC */ if (FALSE == multiBit) { IX_OSAL_WRITE_LONG (tstECCRegAddr, IX_PARITYENACC_CODELET_SINGLE_BIT_ERROR_BIT_0_SYNDROME); } /* configure ECC Test Register to generate multi bit bad ECC */ else { IX_OSAL_WRITE_LONG (tstECCRegAddr, IX_PARITYENACC_CODELET_MULTI_BIT_ERROR_SYNDROME); } /* perform write to generate bad ECC */ IX_OSAL_WRITE_LONG (memAddr4ECCErrorInjection, 0); /* configure ECC Test Register to stop generating bad ECC */ IX_OSAL_WRITE_LONG (tstECCRegAddr, 0); /* perform read to cause ECC error */ if (TRUE == injectNow) { IX_OSAL_READ_LONG (memAddr4ECCErrorInjection); } return IX_SUCCESS;} /* end of ixParityENAccCodeletECCErrorInject function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletParityConfigure ( IxParityENAccHWParityConfig *pENConfig) * * @brief Modify parity configuration. After modification, check the * configuration to make sure it is configured as desired. * * @param pENConfig IxParityENAccHWParityConfig * [in] - pointer to * IxParityENAccHWParityConfig buffer. * * @return IX_STATUS * @li IX_SUCCESS - configure parityENAcc successfully * @li IX_FAIL - fail */PRIVATE IX_STATUSixParityENAccCodeletParityConfigure (IxParityENAccHWParityConfig *pENConfig){ IxParityENAccStatus pENStatus; IxParityENAccHWParityConfig pENConfigTmp; if (NULL == pENConfig) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityConfigure: pass in pointer is null\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* configure Parity Error Notifier with new setting */ pENStatus = ixParityENAccParityDetectionConfigure (pENConfig); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityConfigure: Failed to configure ParityENAcc, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return IX_FAIL; } /* query to retrieve recently configured parity configuration */ pENStatus = ixParityENAccParityDetectionQuery (&pENConfigTmp); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityConfigure: Failed to query ParityENAcc config, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return IX_FAIL; } /* make sure parity configuration is configured as desired */ if (0 != memcmp ((void *)pENConfig, (void *)&pENConfigTmp, sizeof (IxParityENAccHWParityConfig))) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityConfigure: ParityENAcc was not configured as desired\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } return IX_SUCCESS;} /* end of ixParityENAccCodeletParityConfigure function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletSDRAMScanTask () * * @brief Perform SDRAM memory scan at background. The memory range for scanning will * be determined here at run time. * * @return void * */PRIVATE voidixParityENAccCodeletSDRAMScanTask (){ UINT32 addr, start, end;#ifdef __linux struct sysinfo sysInfo; UINT32 size; /* initialize sysinfo buffer */ memset (&sysInfo, 0, sizeof (struct sysinfo)); /* get total memory size */ si_meminfo (&sysInfo); /* the totalram returned by si_meminfo is total memory less kernel reserved memory */ size = ((UINT32) sysInfo.totalram) << PAGE_SHIFT; if (0 == size) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScanTask: failed to get memory size\n", 0, 0, 0, 0, 0, 0); /* terminate parityENAcc codelet execution */ ixParityENAccCodeletQuit (); return; } /* get memory scan start address */ start = (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (IX_PARITYENACC_CODELET_SDRAM_BASE_ADDR); /* compute memory scan end address, end address (0 relative) is size - 1 */ end = (start - IX_PARITYENACC_CODELET_SDRAM_SCAN_START_OFFSET) + (size - 1);#elif defined(__vxworks) /* get memory scan start address */ start = (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (IX_PARITYENACC_CODELET_SDRAM_BASE_ADDR); /* get memory scan end address */ end = (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (sysMemTop ()); if (0 == end) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScanTask: failed to get memory end address\n", 0, 0, 0, 0, 0, 0); /* terminate parityENAcc codelet execution */ ixParityENAccCodeletQuit (); return; }#else #error unsupported OS#endif ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletSDRAMScanTask: start %08x end %08x\n", start, end, 0, 0, 0, 0); while (TRUE) { /* continuously read 4 bytes a time throughout the entire SDRAM */ for (addr = start; addr < end - 4; addr+=4) { /* user requests to terminate SDRAM memory scan */ if (TRUE == ixParityENAccCodeletTerminate) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletSDRAMScanTask: user terminated SDRAM memory scan.\n", 0, 0, 0, 0, 0, 0); return; } /* * preempt this task after scanning one segment of memory. * One segment is 256 Kb. */ if (0 == (addr % IX_PARITYENACC_CODELET_SCAN_SEGMENT_SIZE)) { /* sleep for 1 ms */ ixOsalSleep (1); } if (0 == (addr % IX_PARITYENACC_CODELET_DISPLAY_INTERVAL)) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletSDRAMScanTask: scan SDRAM @ %08x\n", addr, 0, 0, 0, 0, 0); } IX_OSAL_READ_LONG (addr); } }} /* end of ixParityENAccCodeletSDRAMScanTask function */ /** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, UINT32 priority, char *label) * * @brief Spawn a thread to execute given function * * @param * func IxOsalVoidFnPtr [in] - pointer to the function that will be * executed after the thread is spawned. * * @param * priority UINT32 [in] - thread's priority * * @param * label char* [in] - pointer to the Thread name's buffer * * @return IX_STATUS * @li IX_SUCCESS - create Thread successfully * @li IX_FAIL - fai to create Thread */PRIVATE IX_STATUS ixParityENAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, UINT32 priority, char *label){ IxOsalThread memScanThread; IxOsalThreadAttr memScanThreadAttr; /* check the validity of function pointer */ if (NULL == func) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletNewThreadCreate: NULL function pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* check the validity of Thread name's buffer pointer */ if (NULL == label) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletNewThreadCreate: NULL Thread name's pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* zero out the thread attribute buffer */ memset ((void *)&memScanThreadAttr, 0, sizeof (IxOsalThreadAttr)); /* setup thread attribute */ memScanThreadAttr.name = label; memScanThreadAttr.priority = priority; if (IX_SUCCESS != ixOsalThreadCreate (&memScanThread, &memScanThreadAttr, (IxOsalVoidFnVoidPtr)func, NULL)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletNewThreadCreate: Failed to create %s thread.\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } if (IX_SUCCESS != ixOsalThreadStart (&memScanThread)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletNewThreadCreate: Failed to start %s thread\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } ixOsalLog (IX_OSAL_LOG_LVL_DEBUG1, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletNewThreadCreate: %s thread is spawned\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_SUCCESS;} /* end of ixParityENAccCodeletNewThreadCreate function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletSDRAMScrub ( IxParityENAccParityErrorContextMessage *pENContext) * * @brief Scrub SDRAM memory to correct single bit ECC error. * As example, this routine will scrub the entire row of * the data (Q-WORD aligned, 16 bytes) that failed. * * @param pENContext IxParityENAccParityErrorContextMessage * [in] - pointer to * IxParityENAccParityErrorContextMessage buffer. * * @return IX_STATUS * @li IX_SUCCESS - scrub memory successfully * @li IX_FAIL - fail */PRIVATE IX_STATUSixParityENAccCodeletSDRAMScrub (IxParityENAccParityErrorContextMessage *pENContext){ IX_STATUS pENStatus; UINT32 count; UINT32 data[4], *rowAddr = NULL, *scrubAddr = NULL; IxParityENAccHWParityConfig pENConfig; if (NULL == pENContext) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScrub: pass in pointer is null\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* * memory scrub is not required on write transaction as MCU * will scrub the memory automatically on write transaction. */ if (IX_PARITYENACC_WRITE == pENContext->pecAccessType) { return IX_SUCCESS; } /* get the current parity configuration */ pENStatus = ixParityENAccParityDetectionQuery (&pENConfig); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScrub: failed to query ParityENAcc config, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return IX_FAIL; } /* * disable single bit ECC error reporting during scrubbing. * The scrubbing routine will read the failed location to * correct single bit ECC error. This read will cause * second ECC error to be reported if single bit ECC error * reporting is not disabled during scrubbing. */ pENConfig.mcuConfig.singlebitDetectEnabled = IX_PARITYENACC_DISABLE; pENStatus = ixParityENAccCodeletParityConfigure (&pENConfig); if (IX_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScrub: Failed to disable single bit ECC error reporting, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return IX_FAIL; } /* * get the Q-word aligned address of the row where the single bit * ECC error occurred. */ rowAddr = (UINT32 *) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext->pecAddress & IX_PARITYENACC_CODELET_QWORD_ALIGNED_MASK); /* * reading the location that failed will trigger ECC hardware * to fix the error, and writing the data back will correct * the data on memory. */ /* read entire row of data (16 bytes) */ for (scrubAddr = rowAddr, count = 0; count < 4; count++) { data[count] = IX_OSAL_READ_LONG (scrubAddr); scrubAddr++; } /* write entire row of data back */ for (scrubAddr = rowAddr, count = 0; count < 4; count++) { IX_OSAL_WRITE_LONG (scrubAddr, data[count]); scrubAddr++; } /* clear the single bit error */ pENStatus = ixParityENAccParityErrorInterruptClear (pENContext); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScrub: failed to clear interrupt, error code %d\n", pENStatus, 0, 0, 0, 0, 0); } /* re-enable single bit ECC error reporting */ pENConfig.mcuConfig.singlebitDetectEnabled = IX_PARITYENACC_ENABLE; pENStatus = ixParityENAccCodeletParityConfigure (&pENConfig); if (IX_SUCCESS != pENStatus)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -