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.

[FAQ] [参考译文] [常见问题解答]:如何在 AM6x/AM243器件上测试 R5F 缓存的 ECC。

Guru**** 2546020 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1427813/faq-how-to-test-ecc-for-r5f-cache-memories-on-am6x-am243-devices

器件型号:SK-AM62B-P1

工具与软件:

是否可以对 R5F 内部高速缓存存储器进行 ECC (SEC/DED)测试? 如果是、请提供相关步骤。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     下表列出了 R5F 高速缓存的类型和支持的错误注入类型:

    " 指令高速缓存读取错误
    指令高速缓存读取时检测到的所有奇偶校验或 ECC 错误均可纠正。"

    因此不支持 I Cache 上的 DED。 注意 ECC 聚合器支持注入、但检查和报告不支持。 这是 ARM IP 限制、因为无法从 I Cache 中恢复 DED 错误。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    以下是在 AM6x/AM243器件上的 R5F 缓存存储器上测试 SEC/DED 的步骤:

    1. 通过在启动序列中设置 ACTLR 寄存器来为 R5缓存存储器启用 ECC。

    (请注意、启用缓存之前启用 ECC 很重要、因为启用缓存后启用 ECC 会导致意外中止)

    分配给该寄存器的值完全取决于您的特定用例。  我们不建议为此寄存器使用任何严格的值。  但是 、考虑到 single-bit 错误会自动纠正、因此应避免中止可纠正的错误。 因此、您可以考虑将 ACTLR 寄存器设置为101、这将导致仅适用于不可纠正的错误的中止。

                         (屏幕截图取自 R5F TRM)

    MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
    BIC r0, r0, #0x1 << 2 // Disable data cache bit
    BIC r0, r0, #0x1 << 12 // Disable instruction cache bit
    DSB
    MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
    ISB // Ensures following instructions are not executed from cache
    MRC p15, 0, r1, c1, c0, 1 // Read Auxiliary Control Register
    ORR r1, r1, #(0x5 << 3)  //Enable ECC for Cache
    MCR p15, 0, r1, c1, c0, 1 // Write Auxiliary Control Register        
    MCR p15, 0, r0, c15, c5, 0 // Invalidate entire data cache
    MCR p15, 0, r0, c7, c5, 0 // Invalidate entire instruction cache
    MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
    ORR r0, r0, #0x1 << 2 // Enable data cache bit
    ORR r0, r0, #0x1 << 12 // Enable instruction cache bit
    DSB
    MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
    ISB 

    2.启用 R5F PMCR 寄存器的导出功能、将缓存事件路由到 ESM/ Pulsar 寄存器。

    asm("MOV R5, #0x0");                                          
    asm("MRC     P15,#0, R5, C9, C12,#0");                  
    asm("ORR     R5, R5, #0x2");                    // Reset event counter        
    asm("MCR     P15,#0, R5, C9, C12,#0");                  
    asm("MRC     P15,#0, R5, C9, C12,#0");                  
    asm("ORR     R5, R5, #0x11");                 
    asm("MCR     P15,#0, R5, C9, C12,#0");                  
    asm("MOV r4, #0x60");        
    asm("MCR p15,#0,r4,c9,c13,#1");

    3. 使用 SDL_ESM_init () API 初始化 ESM 模块并启用与 R5F 存储器对应的 ECC 事件:(随附的屏幕截图适用于 AM62x。 其他器件也会映射类似的事件)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    4.在测试每个 RAM ID 之前、对整个 DCache/ICache 执行失效和回写

    DCache:

    CacheP_wbInvAll(CacheP_TYPE_L1D)

    ICache:

    CacheP_wbInvAll(CacheP_TYPE_L1P)

    5.通过从高速缓存中执行32KB 的读操作来用虚值填充高速缓存。

    DCache:

    #define ARRAY_SIZE 32*1024 // Size of the array in bytes (32KB)    
    uint8_t a[ARRAY_SIZE];    
    uint8_t b[ARRAY_SIZE];    
    for(uint32_t iii=0;iii<ARRAY_SIZE;iii++)    
    {      
    a[iii]=(iii%256)+1;    
    }

    ICache  

    您可以执行8192个虚拟指令的读取以完全填充 ICache。

    void Fill_ICache()
    {
        asm("MOV R0, #0x0");
        asm("MOV R0, #0x0");
        .
        .
        .(8192 times)
        .
        asm("MOV R0, #0x0");
    }

    6. 使用 ECC Aggr. (下表中列出了 ECC 聚合设置)

    下面为 AM62x 添加了示例代码:(所有器件的代码都是相同的。 只需修改 ECC 聚合器、基址、具体取决于所使用的器件和 R5内核)

    a.对于 single-bit 错误注入:

    uint32_t *ptr2=(uint32_t *)0x3f00d008; //Set RAM ID     
    *ptr2=0xD; // RAM ID 13 - DData0 RAM ID
    uint32_t *ptr3=(uint32_t *)0x3f00d014; // ECC Ctrl Reg    
    *ptr3=0x28;
    uint32_t *ptr5=(uint32_t *)0x3f00d008; // ECC vector Reg
    *ptr5=0x148000;
    while(((*ptr5>>24)&0x1)!=1) // Polling the Read done bit to ensure ECC aggr. gets properly updated
    
    {
    
        ;
    
    }
    asm("NOP"); 

    b.对于双位错误注入:

    uint32_t *ptr2=(uint32_t *)0x3f00d008; //Set RAM ID     
    *ptr2=0xD; // RAM ID 13 - DData0 RAM ID
    uint32_t *ptr4=(uint32_t *)0x3f00d01C; //ECC Error Control2 reg    
    *ptr4=0x30002; 
    uint32_t *ptr3=(uint32_t *)0x3f00d014; // ECC Ctrl Reg    
    *ptr3=0x28;
    uint32_t *ptr5=(uint32_t *)0x3f00d008; // ECC vector Reg
    *ptr5=0x148000;
    while(((*ptr5>>24)&0x1)!=1) // Polling the Read done bit to ensure ECC aggr. gets properly updated
    
    {
    
        ;
    
    }
    asm("NOP"); 

    使用上述示例代码作为参考、可以对不同的 RAM ID 进行以下设置:  

    DCache RAM
    记录
    DTAG

    ECC 错误 Ctlr1寄存器(0x18)

    0xFD

    ECC Ctlr 寄存器(0x14)

    0x48

    (FORCE_sec + ERROR_ONCE)

    ECC 错误 Ctlr2寄存器(0x1C)

    0x30002

    ECC Ctlr 寄存器(0x14)

    0x30

    (FORCE_DED + FORCE_n_ROW)

    DDIrty

    ECC Ctlr 寄存器(0x14)

    0x28

    (FORCE_sec + FORCE_n_ROW)

    ECC 错误 Ctlr2寄存器(0x1C)

    0x30002

    ECC Ctlr 寄存器(0x14)

    0x30

    (FORCE_DED + FORCE_n_ROW)

    DDATA

    ECC Ctlr 寄存器(0x14)

    0x28

    (FORCE_sec + FORCE_n_ROW)

    ECC 错误 Ctlr2寄存器(0x1C)

    0x30002

    ECC Ctlr 寄存器(0x14)

    0x30

    (FORCE_DED + FORCE_n_ROW)

    ITAG

    ECC 错误 Ctlr1寄存器(0x18)

    0xFD

    ECC Ctlr 寄存器(0x14)

    0x48

    (FORCE_sec + ERROR_ONCE)

    不适用

    iDATA

    ECC Ctlr 寄存器(0x14)

    0x28

    (FORCE_sec + FORCE_n_ROW)

    不适用

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    7.循环遍历整个 DCache 以触发 Data 和 Dtag RAM ID 错误。 对于 ddirty RAM、通过从高速缓存内存读取不同的32KB 来清除整个 DCache。 同样、 循环通过整个 ICache 来触发 iDATA 和 Itag RAM ID 的错误

    DCache:

    for(uint32_t i=0;i<ARRAY_SIZE;i++)    
    {    
    b[i]=a[i];    // Same arrays as defined in Step 5
    } 

    ICache:

    Fill_ICache() //Same function as defined in Step 5

    注:

    必须在 ISR (针对 single-bit 错误)内部额外禁用错误注入或通过将 ECC Ctlr 寄存器(0x14)设置为0来中止处理程序(针对 double-bit 错误)、以防止进一步的错误注入。

    // Add the below code inside the ISR/Abort Handler whenever an ECC error is detected
    
    // if error == R5F Cache ECC Error {
        uint32_t *ptr3=(uint32_t *)0x3f00d014; // ECC Ctrl Reg    
        *ptr3=0x0;
        uint32_t *ptr5=(uint32_t *)0x3f00d008; // ECC vector Reg
        *ptr5=0x148000;
        while(((*ptr5>>24)&0x1)!=1) // Polling the Read done bit to ensure ECC aggr. gets properly updated
        
        {
        
            ;
        
        }
    //}
    

    2.在执行双位错误注入时、我们可以获得对应于 DData 和 Dtag RAM ID 的同步中止和对应于 DDirty RAM 的异步中止。 如果触发异步中止检查并清除 CPSR 寄存器的 A 位存在延迟、则应在检测到错误后立即触发中止。