主题中讨论的其他器件:SysConfig
工具与软件:
你好
在我们的产品中、我们有 R5 Core0应用、它应该使用该 ECC 外设监控 DDR 存储器上的位翻转。 在我们的硬件上、我们使用引导流程、这样 u-boot 加载 Linux 内核、然后 R5内核端应用程序通过/lib/firmware.加载 使用此 ECC API 时会遇到一些问题:
1. 尽快 DDR_enableInlineECC (true) 称为整个系统冻结、然后由看门狗重新启动
2.如果我使用 SDL_DPL_registerInterrupt (请参阅下面的代码) API、用于根据 TRM (DDR16SS0_DDRSS_DRAM_ECC_CORR_ERR_LVL_0和 DDR16SS0_DDRSS_DRAM_ECC_Uncorr_ERR_LVL_0)注册中断处理程序或中断6和69。Linux 系统仍有响应、但 R5代码侧的应用程序冻结。
我从名为 DDR_ECC_TEST_MAIN_ESM_am64x-sk_r5fss0-0_nortos_ti-arm-clang 的 MCU SDK 中尝试了示例、但该代码在本例中根本不起作用。 您能否查看该代码、并了解缺失或配置错误的内容?
第页 s 我们还根据本 教程在 u-boot 端上启用了 ECC
应用部件:
#define DDR16SS0_DDRSS_DRAM_ECC_CORR_ERR_LEVEL_0 6
#define DDR16SS0_DDRSS_DRAM_ECC_UNCORR_ERR_LEVEL_0 69
#define DDR_START_ADDR (0x80000000u)
/* Memory block for which ECC is calculated (256 Bytes) */
#define DDR_EMIF_ECC_MEM_BLOCK_SIZE 0x100
/* ECC data size per block (32 Bytes) */
#define DDR_EMIF_ECC_DATA_SIZE_PER_BLOCK 0x20
#define DDR_ECC_REGION0_START 0x20100000
#define DDR_MEM_ECC_TEST_ADDR (DDR_START_ADDR + DDR_ECC_REGION0_START + DDR_EMIF_ECC_MEM_BLOCK_SIZE)
static pSDL_DPL_HwipHandle uncorrIntrHandle, corrIntrHandle;
static volatile uint32_t uncorrectableErrorFlag = false,correctableErrorFlag = false;
static uintptr_t DDRGetTranslatedAddress (uintptr_t memAddress)
{
uint32_t memIndex;
uintptr_t translatedMemAddr;
memIndex = (memAddress - DDR_START_ADDR)/DDR_EMIF_ECC_MEM_BLOCK_SIZE;
if ((memIndex & 0x1u) == 0)
{
translatedMemAddr = memAddress + ((memIndex)*DDR_EMIF_ECC_DATA_SIZE_PER_BLOCK);
}
else
{
translatedMemAddr = memAddress + ((memIndex+1u)*DDR_EMIF_ECC_DATA_SIZE_PER_BLOCK);
}
return translatedMemAddr;
}
void ECC_UncorrectableErrorInterruptHandler(void * args)
{
uncorrectableErrorFlag = true;
DDR_clearECCError (DDR_ECC_2B_ERROR);
}
void ECC_CorrectableErrorInterruptHandler(void * args)
{
correctableErrorFlag = true;
DDR_clearECCError (DDR_ECC_1B_ERROR);
}
uint32_t RAM_ErrorDetectionInterruptInit()
{
int32_t ret = SDL_PASS;
DebugP_log("ECC Error interrupt registration\r\n");
//if registering below interrupts is enabled application starts but freezes at moment when SDL_DPL_registerInterrupt is called
#if 1
SDL_DPL_HwipParams intrParams = {
.intNum = DDR16SS0_DDRSS_DRAM_ECC_UNCORR_ERR_LEVEL_0,
.callback = &ECC_UncorrectableErrorInterruptHandler,
.callbackArg = (uintptr_t)NULL
};
if((ret = SDL_DPL_registerInterrupt(&intrParams,(pSDL_DPL_HwipHandle*)&uncorrIntrHandle)) != SDL_PASS)
{
DebugP_log("ECC Uncorrectable Error interrupt registration failed! Error: %#x\r\n",ret);
return ret;
}
intrParams.intNum = DDR16SS0_DDRSS_DRAM_ECC_CORR_ERR_LEVEL_0;
intrParams.callback = &ECC_CorrectableErrorInterruptHandler;
intrParams.callbackArg = (uintptr_t)NULL;
if((ret = SDL_DPL_registerInterrupt(&intrParams,(pSDL_DPL_HwipHandle*)&corrIntrHandle)) != SDL_PASS)
{
DebugP_log("ECC Correctable Error interrupt registration failed! Error: %#x\r\n",ret);
return ret;
}
#endif
//enable 1 bit error interrupt
//CSL_REG32_FINS(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_V2A_INT_SET_REG, EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN,0x01);
//HW_WR_FIELD32(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_V2A_INT_SET_REG, CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN,0x01);
//enable 2 bit error interrupt
//CSL_REG32_FINS(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_V2A_INT_SET_REG, EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN,0x01);
//HW_WR_FIELD32(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_V2A_INT_SET_REG,CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN,0x01);
CSL_emifEnableECCInterrupts((CSL_emif_sscfgRegs*)CSL_DDR16SS0_SS_CFG_BASE,
CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC1BERR_EN_MASK
| CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECCM1BERR_EN_MASK
| CSL_EMIF_SSCFG_V2A_INT_SET_REG_ECC2BERR_EN_MASK);
return ret;
}
volatile uint32_t * translatedMemPtr = NULL;
static void printRegs()
{
for(int i=0; i<=CSL_EMIF_SSCFG_ECC_2B_ERR_MSK_LOG_REG; i+=4)
{
uint32_t regValue = HW_RD_REG32(CSL_DDR16SS0_SS_CFG_BASE + i);
DebugP_log("%d Reg: %#lx (offset: %#x) | value: %#lx\r\n",i,(long unsigned int)CSL_DDR16SS0_SS_CFG_BASE+i,i,(long unsigned int)regValue);
}
}
uint32_t RAM_ErrorDetectionInit()
{
DebugP_log("Initializing RAM error detection component\r\n");
DDR_enableInlineECC (false);
/*
ECC 1-bit error threshold.
The bridge will generate an interrupt when the ECC
1-bit error count is equal to or greater than this threshold.
A value of 0 will disable the generation of interrupt.
*/
HW_WR_FIELD32(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_ECC_1B_ERR_THRSH_REG,CSL_EMIF_SSCFG_ECC_1B_ERR_THRSH_REG_ECC_1B_ERR_THRSH,0x01);
DDR_clearECCError (DDR_ECC_ERR_ALL);
RAM_ErrorDetectionInterruptInit();
printRegs();
//whole Linux system freezes when enabling ECC and then reboot occuring
//DDR_enableInlineECC(true);
/*
Set 1 to enable ECC verification for read accesses when ecc_en=1.
The value of this field is ignored when ecc_en=0.
This bit must be set and kept static before using DDR.
*/
//HW_WR_FIELD32(CSL_DDR16SS0_SS_CFG_BASE + CSL_EMIF_SSCFG_ECC_CTRL_REG,CSL_EMIF_SSCFG_ECC_CTRL_REG_ECC_CK,0x01);
#if 0
uint32_t * testAddr = (uint32_t *) (DDR_MEM_ECC_TEST_ADDR);
CacheP_wbInv ((void *)testAddr, 4, CacheP_TYPE_ALL);
uint32_t memoryCellValue = *testAddr;
/* Flip one bit to introduce error */
memoryCellValue ^= 0x00010000u;
/* Calculate translated address */
translatedMemPtr = (volatile uint32_t *)(DDRGetTranslatedAddress ((uintptr_t)testAddr));
/* Now corrupt the value */
*(translatedMemPtr) = memoryCellValue;
CacheP_wbInv ((void *)translatedMemPtr, 4, CacheP_TYPE_ALL);
DDR_enableInlineECC(true);
/* Invalidate cache */
CacheP_inv ((void *)testAddr, 4, CacheP_TYPE_ALL);
/* Read value to trigger error */
memoryCellValue = *testAddr;
#endif
return SDL_PASS;
}
SysConfig 器件:
esm1.$name = "CONFIG_ESM0"; esm1.esmNotifier.create(4); esm1.esmNotifier[0].$name = "CONFIG_ESM_NOTIFY0"; esm1.esmNotifier[0].errorNumber = 162; esm1.esmNotifier[0].notify = "ESM_Callback"; esm1.esmNotifier[1].$name = "CONFIG_ESM_NOTIFY1"; esm1.esmNotifier[1].errorNumber = 112; esm1.esmNotifier[1].setIntrPriorityLvl = "LOW"; esm1.esmNotifier[1].notify = "DCC0_IntrErrHandler"; esm1.esmNotifier[2].$name = "CONFIG_ESM_NOTIFY2"; esm1.esmNotifier[2].setIntrPriorityLvl = "LOW"; esm1.esmNotifier[2].errorNumber = 69; esm1.esmNotifier[2].notify = "ECC_UncorrectableErrorInterruptHandler"; esm1.esmNotifier[3].$name = "CONFIG_ESM_NOTIFY3"; esm1.esmNotifier[3].errorNumber = 6; esm1.esmNotifier[3].setIntrPriorityLvl = "LOW"; esm1.esmNotifier[3].notify = "ECC_CorrectableErrorInterruptHandler";
BR
雅库布