0

I am searching for how to test data bus between CPU and memory.

I found the 'walking 1's test' C source code. (link : https://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/software-based-memory-testing.html )

So, I compiled the C code to assembly (by ARM gcc) to understand the atomic CPU/memory action in H/W level.

By looking at assembly carefully, I think this doesn't work for testing the data bus.

Here's the C code and assembly.

#define ul unsigned long

ul DataBusTest_Walking_1(volatile ul* address)
{
    ul pattern;

    for (pattern = 1; pattern != 0; pattern <<= 1)
    {
        *address = pattern;
        if (*address != pattern)
        {
            return(pattern);
        }
    }
}
DataBusTest_Walking_1:
        push    {r7}
        sub     sp, sp, #20
        add     r7, sp, #0
        str     r0, [r7, #4]
        movs    r3, #1
        str     r3, [r7, #12]
        b       .L2
.L5:
        ldr     r3, [r7, #4]
        ldr     r2, [r7, #12]
        str     r2, [r3]
        ldr     r3, [r7, #4]
        ldr     r3, [r3]
        ldr     r2, [r7, #12]
        cmp     r2, r3
        beq     .L3
        ldr     r3, [r7, #12]
        b       .L1
.L3:
        ldr     r3, [r7, #12]
        lsls    r3, r3, #1
        str     r3, [r7, #12]
.L2:
        ldr     r3, [r7, #12]
        cmp     r3, #0
        bne     .L5
.L1:
        mov     r0, r3
        adds    r7, r7, #20
        mov     sp, r7
        ldr     r7, [sp], #4
        bx      lr

I will explain the code briefly.

In C code, write the pattern value into the memory location 'address'.

pattern value changes like this : (walking 1)

0x00000001(00000 ..... 000001)

0x00000002(00000 ..... 000010)

0x00000004(00000 ..... 000100)

0x00000008(00000 ..... 001000) ...

If the data bus has problems, writing pattern value to memory will not work.

So, *address != pattern.

Then, detect the data bus problem.

However, by looking at assembly carefully, I found that a problem exists.

At the beginning of the function DataBusTest_Walking_1, local variable 'pattern' exists in memory.

Before writing 'pattern value' into memory location 'address', CPU should load the 'pattern value' from memory.

And, this is the problem point. When load the 'pattern value', because of the data bus problem, CPU will load incorrect 'pattern value'.

Then, writing the 'incorrect pattern value' to the memory location 'address'.

Then, load the 'incorrect pattern value' from the memory location 'address'.

So, when comparing pattern and *address if (*address != pattern), 'incorrect pattern value' == 'incorrect pattern value' happens.

Though the data bus problem exists, we can't detect it finally.

Anyone can prove this test code work?

  • 2
    Are you compiling with optimizations? With optimization off, compilers like gcc will keep all local variables in memory, and load/store them on every access. With optimizations, you should see `pattern` optimized into a register, so that it need not be loaded from memory. See for instance https://godbolt.org/z/Gjchz7xhM where `pattern` is in `r0`. – Nate Eldredge Jun 01 '21 at 13:51
  • 3
    That said, if you need full control over when memory accesses do or don't happen, it's not really going to work to write it in a higher level language; the compiler will assume that it can access memory freely, and there won't really be any way to inhibit that in general. You will need to write it in assembly by hand. – Nate Eldredge Jun 01 '21 at 13:52
  • Thank you so much, Nate Eldredge! I checked the link. With compiler optimization, the problem is solved. Thank you :) – gibum.park Jun 02 '21 at 01:07
  • note 0x0001 0x0010, 0x0100 is not a walking one 0x0001 0x0002 0x0004 0x0008 0x0010 etc are a walking ones test. – old_timer Jun 02 '21 at 03:24

0 Answers0