SPRZ488E March   2022  – May 2024 AM2631 , AM2631-Q1 , AM2632 , AM2632-Q1 , AM2634 , AM2634-Q1

 

  1.   1
  2. 1Usage Notes and Advisories Matrices
  3. 2Silicon Usage Notes
    1.     i2324
    2.     i2348
    3.     i2364
  4. 3Silicon Advisories
    1.     i2310
    2.     i2311
    3.     i2313
    4.     i2329
    5.     i2345
    6.     i2346
    7.     i2347
    8.     i2349
    9.     i2350
    10.     i2352
    11.     i2353
    12.     i2354
    13.     i2355
    14.     i2356
    15.     i2357
    16.     i2358
    17.     i2359
    18.     i2374
    19.     i2375
    20.     i2386
    21.     i2392
    22.     i2393
    23.     i2394
    24.     i2395
    25.     i2401
    26.     i2402
    27.     i2403
    28.     i2404
    29.     i2405
    30.     i2427
    31.     i2428
    32.     i2433
    33.     i2438
    34.     i2439
  5.   Trademarks
  6. 4Revision History

i2433

ICSS: Reading the 64-bit IEP timer does not have a lock MSW logic when LSW is read

Details:

IEPx 64-bit timestamp can be incorrect when lower 32-bit data is 0xFFFFFFFC or above (at 250MHz). In this case the upper 32-bit value is updated but lower value is the old number. The issue is seen when IEP counter (IEP_COUNT_REG1 : IEP_COUNT_REG0) is read back-to-back from ICSS PRU cores.

Example 1:

1st read : 0x000000D0(Upper):0xFFFFFFFC(lower)

2nd read : 0x000000D0(Upper):0x00000028(lower)

Example 2:

1st read : 0x000000D7(Upper):0xFFFFFFFC(lower)

2nd read : 0x000000D7(Upper):0x0000002C(lower)

Example 3:

1st read : 0x000000D6(Upper):0xFFFFFFF0(lower)

2nd read : 0x000000D7(Upper):0xFFFFFFFC((lower)

As shown above, this leads to timer increment behavior that is non-monotonic or timer differences to be unusually large as in Example 3 . This is due to 1 cycle race condition when loading 64-bit value from IEPx counter.

Workaround(s):

Note: these workarounds exist in SDK9.2 and later

Workaround in C for PRU:

uint64_t timestamp = (uint64_t) (0x2E0010); 

/* Workaround starts here */

if ((timestamp & 0xFFFFFFFF) >= 0xFFFFFFFC)

{     timestamp = *(uint64_t*) (0x2E0010); } 

/* Workaround ends here */

Workaround in assembly for PRU:

 ldi32 r4, 0xFFFFFFFC ; 0-4 for 250MHz clock
    ;load 64-bit timestamp to r2:r3
    lbco &r2, c26, 0x10, 8
    qbgt skip_iep_read_errata. r2, r4
    ;re-read IEP if IEP_COUNTER_LOW >= 0xFFFF_FFFC
    lbco &r2, c26, 0x10, 8
skip_iep_read_errata: 

Workaround in C for R5F, A53:

uint64_t getIepTimeStamp64 (void)
{
    uint64_t u64Timestamp1 = (volatile uint64_t)(0x300AE010);
    uint64_t u64Timestamp2 = (volatile uint64_t)(0x300AE010);
    if (u64Timestamp2 > u64Timestamp1)
    {
#ifdef __DEBUG
        if (((u64Timestamp2 >> 32)-(u64Timestamp1 >> 32)) == 1)
        {
            /* HW errata fixed due to picking u64Timestamp1*/
            if ((u64Timestamp2 & 0xFFFFFFFF) >= (u64Timestamp1 & 0xFFFFFFFF))
           

{                 DebugP_log ("Errata fixed (1): %llx : %llx\r\n", 
        u64Timestamp1, u64Timestamp2);             }

        }
#endif
        return u64Timestamp1;
    }
    else
    {
#ifdef __DEBUG
        if ((u64Timestamp2 & 0xFFFFFFFF) < (u64Timestamp1 & 0xFFFFFFFF))
       

{             /* Adjust the IEP MSW in the case running into HW errata */             
    DebugP_log ("Errata fixed (2): %llx : %llx\r\n", u64Timestamp1, 
u64Timestamp2);         }

#endif
        /* HW errata fixed due to picking u64Timestamp2*/
        return u64Timestamp2;
    }
}