📄 ixparityenacccodelet.c
字号:
{ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletSDRAMScrub: Failed to re-enable single bit ECC error reporting, error code %d\n", pENStatus, 0, 0, 0, 0, 0); } ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletSDRAMScrub: virtual address %08x [physical address %08x] is scrubbed\n", (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext->pecAddress), pENContext->pecAddress, 0, 0, 0, 0); return IX_SUCCESS;} /* end of ixParityENAccCodeletSDRAMScrub function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletParityErrActionPerformed ( IxParityENAccParityErrorContextMessage *pENContext) * * @brief Determine actions required to handle the parity error * * The actions can be one or more of the followings : * (1) reboot the board * (2) scrub the memory * (3) clear the interrupt * (4) log the error * * The clients need to define the most appropriate actions for * each parity error scenario in their application. * * @param pENContext IxParityENAccParityErrorContextMessage * [in] - * pointer to IxParityENAccParityErrorContextMessage buffer. * * @return void */PRIVATE voidixParityENAccCodeletParityErrActionPerformed ( IxParityENAccParityErrorContextMessage *pENContext){ IxParityENAccStatus pENStatus; IxParityENAccHWParityConfig pENConfig; if (NULL == pENContext) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrActionPerformed: pass in pointer is null\n", 0, 0, 0, 0, 0, 0); return; } switch (pENContext->pecParitySource) { /* single bit ECC error */ case IX_PARITYENACC_MCU_SBIT: { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletParityErrActionPerformed: single bit ECC error's detected @ address: %08x, Syndrome: %02x, Requester: %s, Access Type: %s\n", (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext->pecAddress), pENContext->pecData, (UINT32) ((IX_PARITYENACC_WRITE >= pENContext->pecRequester) ? ixParityENAccCodeletRequesterLabel[pENContext->pecRequester] : "N/A"), (UINT32) ((IX_PARITYENACC_AHB_BUS >= pENContext->pecAccessType) ? ixParityENAccCodeletAccessTypeLabel[pENContext->pecAccessType] : "N/A"), 0, 0); /* get the parity configuration */ pENStatus = ixParityENAccParityDetectionQuery (&pENConfig); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrActionPerformed: failed to query ParityENAcc config, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return; } /* * scrub the memory if single bit ECC correction * is enabled. */ if (IX_PARITYENACC_ENABLE == pENConfig.mcuConfig.singlebitCorrectionEnabled) { if (IX_SUCCESS != ixParityENAccCodeletSDRAMScrub (pENContext)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrActionPerformed: failed to scrub the memory\n", 0, 0, 0, 0, 0, 0); } } break; } /* end of case IX_PARITYENACC_MCU_SBIT */ case IX_PARITYENACC_PBC_TARGET: case IX_PARITYENACC_EBC_EXTMST: { /* clear the interrupt */ pENStatus = ixParityENAccParityErrorInterruptClear (pENContext); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrActionPerformed: Failed to clear interrupt, error code %d\n", pENStatus, 0, 0, 0, 0, 0); } ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletParityErrActionPerformed: %s parity error is detected @ address: %08x, Access Type: %s, Requester: %s, Data: %08x\n", (UINT32) ((IX_PARITYENACC_EBC_EXTMST >= pENContext->pecParitySource) ? ixParityENAccCodeletSourceLabel[pENContext->pecParitySource] : "N/A"), (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext->pecAddress), (UINT32) ((IX_PARITYENACC_WRITE >= pENContext->pecAccessType) ? ixParityENAccCodeletAccessTypeLabel[pENContext->pecAccessType] : "N/A"), (UINT32) ((IX_PARITYENACC_AHB_BUS >= pENContext->pecRequester) ? ixParityENAccCodeletRequesterLabel[pENContext->pecRequester] : "N/A"), pENContext->pecData, 0); break; } /* end of case IX_PARITYENACC_PBC_TARGET and IX_PARITYENACC_EBC_EXTMST */ case IX_PARITYENACC_MCU_MBIT: case IX_PARITYENACC_AQM: case IX_PARITYENACC_EBC_CS: case IX_PARITYENACC_NPE_A_IMEM: case IX_PARITYENACC_NPE_A_DMEM: case IX_PARITYENACC_NPE_A_EXT: case IX_PARITYENACC_NPE_B_IMEM: case IX_PARITYENACC_NPE_B_DMEM: case IX_PARITYENACC_NPE_B_EXT: case IX_PARITYENACC_NPE_C_IMEM: case IX_PARITYENACC_NPE_C_DMEM: case IX_PARITYENACC_NPE_C_EXT: case IX_PARITYENACC_SWCP: case IX_PARITYENACC_MCU_OVERFLOW: case IX_PARITYENACC_PBC_INITIATOR: { /* clear the interrupt */ pENStatus = ixParityENAccParityErrorInterruptClear (pENContext); if (IX_PARITYENACC_SUCCESS != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrActionPerformed: failed to clear interrupt, error code %d\n", pENStatus, 0, 0, 0, 0, 0); } ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletParityErrActionPerformed: %s parity error is detected @ address: %08x, Access Type: %s, Requester: %s, Data: %08x\n", (UINT32) ((IX_PARITYENACC_EBC_EXTMST >= pENContext->pecParitySource) ? ixParityENAccCodeletSourceLabel[pENContext->pecParitySource] : "N/A"), (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext->pecAddress), (UINT32) ((IX_PARITYENACC_WRITE >= pENContext->pecAccessType) ? ixParityENAccCodeletAccessTypeLabel[pENContext->pecAccessType] : "N/A"), (UINT32) ((IX_PARITYENACC_AHB_BUS >= pENContext->pecRequester) ? ixParityENAccCodeletRequesterLabel[pENContext->pecRequester] : "N/A"), pENContext->pecData, 0); /* reboot the board */ ixParityENAccCodeletReboot (); break; } default: { /* reboot the board */ ixParityENAccCodeletReboot (); } } /* end of switch (pENContext->pecParitySource) */} /* end of ixParityENAccCodeletParityErrActionPerformed function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletParityErrHandler () * * @brief Handle parity error informed by Parity Error Notifier. * * This is a callback routine called by Parity Error Notifier when * parity error is detected. Interrupts can be stacked. It is possible * that multiple parity errors occurred at the same time. So, * making sure all parity errors are handled is required here. * * @return void */PRIVATE voidixParityENAccCodeletParityErrHandler (){ IxParityENAccParityErrorContextMessage pENContext; IxParityENAccStatus pENStatus; UINT32 count = 0; do { /* initialize IxParityENAccParityErrorContextMessage buffer */ memset (&pENContext, 0xFF, sizeof (IxParityENAccParityErrorContextMessage)); /* get parity error context */ pENStatus = ixParityENAccParityErrorContextGet (&pENContext); if (IX_PARITYENACC_SUCCESS == pENStatus) { count++; /* handle legitimate parity error */ ixParityENAccCodeletParityErrActionPerformed (&pENContext); } else if (IX_PARITYENACC_NO_PARITY != pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletParityErrHandler: Failed to get context, error code %d\n", pENStatus, 0, 0, 0, 0, 0); return; } } while (IX_PARITYENACC_NO_PARITY != pENStatus); if (0 == count) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletParityErrHandler: no parity error is detected\n", 0, 0, 0, 0, 0, 0); }} /* end of ixParityENAccCodeletParityErrHandler function */#ifdef __vxworks#ifdef _DIAB_TOOL__asm volatile UINT32 _ixParityENAccCodeletStatusRegGet(void){! "r0" mrc\tp15, 0, r0, c5, c0, 0; /* return value is returned through register R0 */}__asm volatile UINT32 _ixParityENAccCodeletAddrRegGet(void){! "r0" mrc\tp15, 0, r0, c6, c0, 0; /* return value is returned through register R0 */}#endif /* #ifdef _DIAB_TOOL *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletDataAbortHandler () * * @brief Handle multi-bit ECC error that caused data abort to occur * * This routine demonstrates how to determine whether the imprecise/precise * data abort is caused by multi-bit ECC error (accessed by XScale). If so, * the multi-bit ECC error will be reported before rebooting the board. If * data abort is related to other type of parity error, then parity error * will be handled. This routine does not intend to demonstrate how data * abort handler should be implemented, so it does not attempt to recover * the data abort. In this data abort handler, the board will be rebooted * at the end. * * @return void */PRIVATE voidixParityENAccCodeletDataAbortHandler (){ IxParityENAccParityErrorContextMessage pENContext; IxParityENAccStatus pENStatus; UINT32 statusReg, addrReg; BOOL impreciseDataAbort; /* * read co-processor 15's register 5 (Fault Status Register) and * register 6 (Fault Address Register), and write their values * to statusReg and addrReg, respectively. */ #ifdef _DIAB_TOOL statusReg = _ixParityENAccCodeletStatusRegGet(); addrReg = _ixParityENAccCodeletAddrRegGet();#else __asm__ volatile ("mrc p15, 0, %0, cr5, cr0, 0;" "mrc p15, 0, %1, cr6, cr0, 0;" :"=&r"(statusReg), "=&r"(addrReg):);#endif /* #ifdef _DIAB_TOOL */ /* determine if the data abort is imprecise or precise */ impreciseDataAbort = IX_PARITYENACC_CODELET_BIT_MASK_CHECK (statusReg, IX_PARITYENACC_CODELET_EXTERNAL_DATA_ABORT) || IX_PARITYENACC_CODELET_BIT_MASK_CHECK (statusReg, IX_PARITYENACC_CODELET_DATA_CACHE_PARITY_ERR); /* initialize IxParityENAccParityErrorContextMessage buffer */ memset (&pENContext, 0xFF, sizeof (IxParityENAccParityErrorContextMessage)); /* get parity error context */ pENStatus = ixParityENAccParityErrorContextGet (&pENContext); /* data abort is not related to parity error */ if (IX_PARITYENACC_NO_PARITY == pENStatus) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletDataAbortHandler: Data abort is not related to parity error\n", 0, 0, 0, 0, 0, 0); } /* parity error did occur at the same time as data abort */ else if (IX_PARITYENACC_SUCCESS == pENStatus) { /* imprecise data abort occurred */ if (TRUE == impreciseDataAbort) { /* * XScale detected multi-bit ECC error and the * error caused imprecise data abort */ if ((IX_PARITYENACC_MCU_MBIT == pENContext.pecParitySource) && (IX_PARITYENACC_MPI == pENContext.pecRequester)) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletDataAbortHandler: XScale detected multi-bit ECC error @ address %08x and the error caused imprecise data abort\n", pENContext.pecAddress, 0, 0, 0, 0, 0); } else { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletDataAbortHandler: Imprecise data abort is not related to parity error, source: %s requester: %s\n", (UINT32) ((IX_PARITYENACC_EBC_EXTMST >= pENContext.pecParitySource) ? ixParityENAccCodeletSourceLabel[pENContext.pecParitySource] : "N/A"), (UINT32) ((IX_PARITYENACC_AHB_BUS >= pENContext.pecRequester) ? ixParityENAccCodeletRequesterLabel[pENContext.pecRequester] : "N/A"), 0, 0, 0, 0); } } /* end of if (TRUE == impreciseDataAbort) */ /* precise data abort occurred */ else if (addrReg == pENContext.pecAddress) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletDataAbortHandler: XScale detected multi-bit ECC error @ address %08x and the error caused precise data abort\n", pENContext.pecAddress, 0, 0, 0, 0, 0); } /* precise data abort is not related to parity error */ else { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixParityENAccCodeletDataAbortHandler: Precise data abort is not related to parity error, source: %s requester: %s address: %08x\n", (UINT32) ((IX_PARITYENACC_EBC_EXTMST >= pENContext.pecParitySource) ? ixParityENAccCodeletSourceLabel[pENContext.pecParitySource] : "N/A"), (UINT32) ((IX_PARITYENACC_AHB_BUS >= pENContext.pecRequester) ? ixParityENAccCodeletRequesterLabel[pENContext.pecRequester] : "N/A"), (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (pENContext.pecAddress), 0, 0, 0); } /* handle parity error */ ixParityENAccCodeletParityErrActionPerformed (&pENContext); } /* end of else if (IX_PARITYENACC_SUCCESS == pENStatus) */ else { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletDataAbortHandler: Data abort occurred but failed to get parity error context\n", 0, 0, 0, 0, 0, 0); } /* reboot the board here if the board is not yet rebooted */ ixParityENAccCodeletReboot ();} /* end of ixParityENAccCodeletDataAbortHandler function */#endif /* end of #ifdef __vxworks *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletReboot () * * @brief Wake up Shut Down Thread to reboot the board * * @return void * */PRIVATE voidixParityENAccCodeletReboot (){ if (IX_SUCCESS != ixOsalSemaphorePost (&ixParityENAccCodeletRebootSemId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixParityENAccCodeletReboot: failed to give semaphore\n", 0, 0, 0, 0, 0, 0); /* proceed with reboot if failing to wake up "Shut Down" task */ IX_PARITYENACC_CODELET_REBOOT(); }} /* end of ixParityENAccCodeletReboot function *//** * @ingroup IxParityENAccCodelet * * @fn ixParityENAccCodeletShutDownTask () * * @brief Sleep most of the time. If it's invoked, terminate parityENAcc codelet execution * and then reboot the board * * In this codelet, the board is rebooted in a thread instead of ISR. The purpose is to give * ixOsalLog opportunity to display data abort and multi-bit ECC handling information. * These informational messages are the only indication that data abort and multi-bit ECC error * do occur and are handled as designed. If the reboot is executed during ISR, the board * will be rebooted before the printout of data abort and multi-bit ECC error handling messages * (observed in vxWorks). Thus, the user may not know why the board is rebooting. * * In summary, spawning a thread to reboot the board is only for demonsration purpose, it may * not be suitable for user application. * * @return void * */PRIVATE void ixParityENAccCodeletShutDownTask (){ ixOsalSemaphoreWait (&ixParityENAccCodeletRebootSemId, IX_OSAL_WAIT_FOREVER); if (TRUE == ixParityENAccCodeletTerminate) return; ixParityENAccCodeletQuit (); /* * sleep for a while to give ixOsalLog opportunity to display data abort * and multi-bit ECC handling information */ ixOsalSleep (500); IX_PARITYENACC_CODELET_REBOOT();} /* end of ixParityENAccCodeletShutDownTask function */ #endif /* __ixp46X */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -