This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Strange behaviour of cache

Note: This was originally posted on 19th November 2011 at http://forums.arm.com

Hi!

I have a Cortex a9 based board (currently only 1core is active another one is waiting for its time to come into a play).
My simplified caching routine in pseudo code looks like this:

Cache(set of parameters){
if(cache_op1)docache_op1();
if(cache_op2)docache_op2();
....
if(cache_opn)docache_opn();
}
An example of cache operation:
     mov  r0, #0
     mcr  p15, 0, r0, c7, c5, 0    ; I cache
     mcr  p15, 0, r0, c7, c5, 6    ; BP
     DSB
     ISB
     bx   lr

The system hangs at some point...
But when I include a delay (several thousands of CPU cycles) it gets stable and works just fine:
Cache(set of parameters){
if(cache_op1)docache_op1();
if(cache_op2)docache_op2();
....
if(cache_opn)docache_opn();
Delay();
}
Disabling/enabling L2 cache doesn't seem to affect the system. So I think it is related to L1 cache.

Having delay in this function isn't acceptable because of performance  issues and frankly speaking I don't know how long it should be delayed  for in every particular case.
I suspect that some caching operations need time to complete. Is there a  mechanism in ARM to ensure that caching operation is complete? I  thought it was done by using the DSB instruction... But it is either  ignored or used for a completely different purpose. If there is no such  mechanism then how should it be handled? I mean if the program continues  to execute while hardware operation is not finished. Otherwise I cannot  explain my workaround with delay.  Any ideas are welcome.

Thanks
  • Note: This was originally posted on 21st November 2011 at http://forums.arm.com


    HI SJS,

    Maybe you can remove the delay at the end of the function and add delay to the cache_ops to see which cache op result the issue. Such as 
    if(cache_op2){ docache_op2(); delay()}
    Please try add some nops to then end of the docache_ops, such as
    mov r0, #0 mcr p15, 0, r0, c7, c5, 0 ; I cache
    mcr p15, 0, r0, c7, c5, 6 ; BP
    DSB
    ISB
       nop
       nop
       nop
    bx lr
    to clean the pipeline.

    It is not possible to separate caching functions from each other. They are all called very frequently. So for example delay for one of the functions will serve as delay for all other functions. I am clueless what can actually cause all this. Do you have any ideas, even weird ones?
  • Note: This was originally posted on 19th November 2011 at http://forums.arm.com

    HI SJS,

    Maybe you can remove the delay at the end of the function and add delay to the cache_ops to see which cache op result the issue. Such as 
    [color=#222222][size=2]if(cache_op2){ docache_op2(); delay()}[/size][/color]
    [color=#222222][size=2]Please try add some nops to then end of the docache_ops, such as[/size][/color]
    [color=#222222][size=2] [/size][/color][color=#222222][size=2]mov r0, #0[/size][/color][color=#222222][size=2] mcr p15, 0, r0, c7, c5, 0 ; I cache [/size][/color]
    [color=#222222][size=2] mcr p15, 0, r0, c7, c5, 6 ; BP[/size][/color]
    [color=#222222][size=2] DSB[/size][/color]
    [color=#222222][size=2] ISB[/size][/color]
       nop
       nop
       nop
    [color=#222222][size=2] bx lr[/size][/color]
    [color=#222222][size=2]to clean the pipeline.[/size][/color]
  • Note: This was originally posted on 22nd November 2011 at http://forums.arm.com

    Can you explain more why "It is not possible to separate caching functions from each other"? From my perspective:
    {
    if(cache_op1) {docache_op1(); delay();}
    if(cache_op2)docache_op2();
    }
    It this works fine, then change it to
    {
    if(cache_op1)docache_op1();
    if(cache_op2) {docache_op2(); delay()}
    }
    If this does not work ,then you can know that docache_op2() is probably the reason to cause the problem and then focus on it.

    It may not be the reason to cause your problem here, but when you perform some operations such as "invalidate/flush/clear all I-Cache D-Cache", I'd suggest you lock all the interrupts.