MPC5554 Unable to flash invalidate cache

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MPC5554 Unable to flash invalidate cache

2,925 Views
schlosserolivie
Contributor I

Hi,

 

I have a problem with MPC5566.

 

When I'm trying to invalidate the L1 cache memory using CFI bit in L1CSR0 register, it sometimes fails (Rise of CABT bit).

The cache is configured in "write-through" mode and the invalidation is done at start of each decrementer exception.

 

My software implements the errata e1031 (http://www.nxp.com/files/32bit/doc/errata/MPC5554_REVB.pdf?fasp=1&WT_TYPE=Errata&WT_VENDOR=FREESCALE...)

 

Can someone confirm that cache invalidation is impossible in this specific case ? Have you a workaround ?

 

Please find below my source code:

;**************************************************************
; Global function : CacheInvalidate                           *
;**************************************************************
        .global CacheInvalidate
CacheInvalidate:
    mflr    r12                           ; save off return address in NV reg

    ; ERRATA e1031
    ; Disable external interrupts MSR[EE] = 0
    ; Disable critical interrupts MSR[CE] = 0
    ; Save the interrupt controllers current priority INTC_CPR[PRI]
    ; Raise the interrupt controllers current priority to maximum INTC_CPR[PRI] = 0xF
    ; Synchronize by executing msync and isync instructions
    ; Execute Invalidation of Cache
    ; After cache invalidation perform the following steps:
    ; Restore the saved priority setting to INTC_CPR[PRI]
    ; Restore MSR[CE] if it was altered
    ; Restore MSR[EE]
   
    mfmsr  r11
    lis    r3, 0xFFFD        # CE = 0
    addi   r3, r3, 0x7FFF    # EE = 0
    and    r3, r3, r11
    mtmsr  r3                # Disable MSR[EE] and MSR[CE]
   
    ; Base address of INTC_CPR = 0xFFF48008
    lis     r13, 0xFFF4
    ori     r13, r13, 0x8008
    lwz     r5, 0x0(r13)        # r5 contains the INTC_CPR[PRI] content
    li      r6, 0x000F
    stw     r6, 0x0(r13)       # set INTC_CPR[PRI] to 0xF
   
    InvalidateCache_l:
    ; Before writing to L1CSR0, execute msync & isync
    ; Invalidate cache: Set L1CSR0[CINV] to 1, other fields unchanged
    mfspr  r3, l1csr0
    ori    r3, r3, 0x0002
    msync
    isync
    mtspr  l1csr0, r3
   
    WaitForInvalidationComplete_l:
    ; Get current status of cache from spr L1CSR0
    ; Mask out all bits except CINV
    ; Compare if CINV, bit 30 is set to 1
    mfspr  r3, l1csr0
    and    r3, r3, r4
    cmpli  r3, 0x0002
    beq    WaitForInvalidationComplete_l
   
    ; Branch to error if cache invalidation was aborted
    ; Get current status of cache from spr L1CSR0
    ; In a scratch register set bit 29 L1CSR0[CABT] to 1, other bits 0
    ; Mask out all bits except CABT
    ; Compare if CABT, bit 29 is set to 1
    ; If there was an aborted invalidation, attempt again
    mfspr  r3, l1csr0
    li     r4, 0x0004
    and    r3, r3, r4
    cmpli  r3, 0x0004
    beq    InvalidateCache_l
   
    ; ERRATA e1031 continue
    ; Restore the saved priority setting to INTC_CPR[PRI]
    ; Restore MSR[CE] if it was altered
    ; Restore MSR[EE]
    stw     r5, 0x0(r13)
    msync
    isync
    mtmsr   r11

    mtlr    r12                           ; get saved return address
    blr

 

Thanks.

 

Best regards,

Olivier

 

 

Labels (1)
0 Kudos
Reply
10 Replies

2,552 Views
schlosserolivie
Contributor I

Hello,

I finally found a solution ! :smileysilly:

I move the call of the function into C function called by the interrupt handler after the enable of the interrupt and I manual disable each interrupt that could append during invalidation. And then it works !

void MainTask(void)

{

MaskSCI_A();

MaskSCI_B();

MaskCANInterrupt();

/* Call CacheInvalidate to clear cache data at start of the PIT */

CacheInvalidate();

UnMaskCANInterrupt();

UnmaskSCI_A();

UnmaskSCI_B();

In my software the cache invalidation was done into the interrupt handler of my periodic task (using Decrementer). Then when the cache invalidation function is executed the interrupt are still disabled (MSR[EE] bit) and then an interrupt can be pending (for exemple : eSCI or CAN in my software). This cause the failure of the invalidation.

0 Kudos
Reply

2,552 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

Hi, are you clearing DIS flag at the beginning of decrementer exception routine?


    /* clear Dec Interrupt Status (DIS) flag */
    asm
    {
        lis  r4, 0x0800 // w1c operation
        mtspr  336, r4  // DIS flag is in spr TSR (spr 336)
    }

0 Kudos
Reply

2,552 Views
schlosserolivie
Contributor I

Hello David,

When I invalidate the cache the DIS is not yet cleared. I do it just after.

0 Kudos
Reply

2,552 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

Try to do it before.
It seems CABT is raised immediately when there is a pending interrupt (even if MSR[EE] is cleared) and there is an attempt to invalidate the cache.

Let me know if it helps or not.

0 Kudos
Reply

2,552 Views
schlosserolivie
Contributor I

Hello david,

Thanks for this quick answer.

I try it but it does not solve the problem. I still have sometimes the CABT bit raised and then each next invalidating of the cache will raise it again.

0 Kudos
Reply

2,552 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

Don't you have some other pending interrupt? Problem is that due to erratum e1031 masking of external interrupt by MSR[EE] is not enough and such interrupt source can abort cache invalidation anyway. It is needed to disable source of interrupt on the particular module's level.

0 Kudos
Reply

2,552 Views
schlosserolivie
Contributor I

Hello,

do you mean that if an interrupt is raised by the INTC during the invalidation, then the invalidation will failed even if the external interrupt was masked due to the set of INTC_CPR[PRI] to 0xF ?

Regards

Olivier

0 Kudos
Reply

2,552 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

According core RM E200Z6_RM_rev0 I would say it is caused by decrementer interrupt that is just blocking cache invalidation due to e1031:

pastedImage_1.png

0 Kudos
Reply

2,552 Views
schlosserolivie
Contributor I

Hello David,

So what is the solution to invalidate cache at start of a Decrementer interrupt ? If I correctly understand what you say, the cache could not be invalidate during Decrementer interrupt.

I check using a debugger and it's also look like I have an interrupt comming from SCI that is raised during the invalidation. But as INTC_CPR[PRI] to 0xF, this shoul not impact the cache.

Thank you for your help.

Olivier

0 Kudos
Reply

2,552 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

I have tried to do some experiments I wasn't never able to achieve mentioned behavior. It seems cache be could be invalidated during decrementer interrupt as well.

Generally I have learned following four options can abort cache invalidation:
1. set MSR[EE], then assert External Interrupt.
2. set MSR[CE], then assert Critical Interrupt.
3. Use the Watchdog Timer or Fixed Interval Timer or Decrementer using the Core's TimeBase unit.
4. Assert NMI.


Note that with devices (as MPC5554) where errata e1031 is present, MSR[EE] even don't need to be set and it'll act same way in relation to cache invalidation abort.


I am just thinking whether your decrementer period is not too short not allowing to invalidate the cache at all as it interrupted by second shoot from decrementer. Maybe you try to stop decrementer operation in decrementer interrupt.

The best would be to prepare simple example code allowing us to reproduce and analyze the issue.
I think it would be appropriate to create a new case for this to get the question to the right person:
https://community.nxp.com/docs/DOC-329745 

0 Kudos
Reply