9

有没有办法在 android 设备 RAM 上进行完整的内存测试?

我正在开发一个驱动程序,但有时我得到某些物理地址的值错误,导致驱动程序进入错误状态。当我遇到问题时,我正在尝试从 RAM 中读取。我认为我设备上 ram 的某些部分已损坏。

4

3 回答 3

7

完整是一个模棱两可的词。这可能意味着不同的温度、电压以及具有不同组件公差的一系列设备。当您站点MemTest86时,我想我明白了。我见过的大多数项目都是基于C的,无法测试所有内容。

这是在Linux下运行的一个- http://www.madsgroup.org/~quintela/memtest/

记录了诸如walk bits等算法。很大程度上取决于您的 RAM 类型。我猜你有某种类型的 SDRAM。SDRAM有许多不同的周期。有单拍读/写、银行间转账、终止突发等。

就个人而言,我们有一个系统,当通过以太网 (DMA) 进行 SSH 传输时,有 5% 的板会出现问题。SSH 涉及到 CPU/内存密集型的加密,并且 DMA 引擎通常执行与 CPU(带有缓存)不同的 SDRAM 周期。

这里有一些要求,

  1. 用于驻留代码的非 SDRAM 内存。
  2. 裸机框架(无缓存、中断、DMA 等)
  3. 关闭 DCache。
  4. 打开代码的 ICache。

另一个限制要求是运行时间。一个完整的SDRAM 测试可能需要数年才能在一块板上运行。我发现伪随机地址/数据测试效果很好。只需取与 SDRAM 大小相对质数的数字并将其用作增量。最简单的情况是1。您可能希望找到其他不断变化的设备rowsbanks以及设备大小;bank size-1例如; 然而,质数会更好,因为你有不同数量的比特一直在变化。在缓存关闭的情况下,您可以使用charshortintlong long指针来测试一些不同的突发长度。这些测试会很慢。您将需要使用ldm/stm对来模拟完整的SDRAM 突发,这些在缓存上更常见,因此您应该使用它们来模拟它们ldm/stm。这也是最快的测试之一。

typedef 无符号字符 b8;
typedef 无符号短 b16;
typedef unsigned long b32;
typedef unsigned long long b64;

/* 使用宏来加速代码。编译器将使用常量
 * _incr 和 _wrap 而不是导致溢出的寄存器。一个
 * 宏集中了内存测试逻辑。
 */
#define MEMTEST(名称,类型,_incr,_wrap)...

/* 顺序测试。*/
MEMTEST(do_mem_seq8, b8, 97, 1)
MEMTEST(do_mem_seq16, b16, 50839, 1)
MEMTEST(do_mem_seq32, b32, 3999971, 1)
MEMTEST(do_mem_seq64, b64, 3999971, 1)

/* 随机测试。这些测试试图随机化数据和
 * 地址访问。
 */

/* 97/0x61 用于 char 和 9999991/0x989677 用于 64MB。*/
MEMTEST(do_mem_rnd8,b8,97,9999991)
/* 64k 的 50839/C697 大素数和 64MB 的 9999991/0x989677 素数。*/
MEMTEST(do_mem_rnd16,b16,50839,9999991)
/* 64MB 的 3999971/3D08E3 素数和 9999991/0x989677 素数。*/
MEMTEST(do_mem_rnd32,b32,3999971,9999991)
/* 64MB 的 3999971/3D08E3 素数和 9999991/0x989677 素数。*/
MEMTEST(do_mem_rnd64,b64,3999971,9999991)

incr是数据增量,wrap是地址增量。突发的算法将是相同的。这是一些内联 gcc 汇编器

    register ulong t1 asm ("r0")  = 0;                              \
    register ulong t2 asm ("r4")  = t1 + incr;                      \
    register ulong t3 asm ("r6")  = t2 + incr;                      \
    register ulong t4 asm ("r8")  = t3 + incr;                      \
        /* Run an entire burst line. */                             \
        __asm__ (" stmia  %[ptr], {%0,%1,%2,%3}\r\n" : :            \
                 "r" (t1), "r" (t2), "r" (t3), "r" (t4),            \
                 [ptr]"r" (start + (addr<<2)) :                     \
                 "memory" );                                        \
        /* Read four 32 bits values. */                             \
        __asm__ (" ldmia   %[ptr], {%0, %1, %2, %3}\r\n" :          \
                 "=r" (t1), "=r" (t2), "=r" (t3), "=r" (t4) :       \
                 [ptr]"r" (start + (addr<<2)) );                    \

这些测试很简单,应该适合代码缓存,这将最大限度地增加 RAM 的压力。我们的主要问题是 DQS 延迟,这对 DDR-SDRAM 至关重要,并且可能与温度和电压有关,并且会随 PCB 布局和材料而变化。

如果您使用 SDRAM 芯片优化内存控制器寄存器,则可以使用Cachbench 。它也可能对测试有用。

另请参阅:Unix Stack Exchange(相同的问题)。我在 Linux 下使用了这些基于C的测试套件,但在我们的案例中它们没有暴露任何问题。memtest86 算法可能没有我上面描述的那么紧张(对于 PCB 故障);尽管测试7burnBX测试已经接近。我认为memtest86可以解决 DRAM 芯片问题,而不是电路板设计问题。

编辑:另一个问题是与 SDRAM 芯片的瞬态/串扰。如果您的设备驱动程序是大电流或高频设备,则 SDRAM 接口可能会产生串扰,或者由于电源变化而获得双时钟。因此, RAM 测试可能不会显示任何问题,并且 SDRAM 错误仅在使用硬件的特定部分时才会发生。还要注意 Android 设备不使用动态时钟并更改 SDRAM 频率。随着时钟的变化,信号可能会发生共振。

于 2013-01-28T15:33:09.103 回答
2

Das U-Boot 可能是 ARM 板上使用最广泛的引导加载程序,它包括一些内存测试功能。

有趣的是,它的自述文件提出了一种可能更便携和/或更有效的替代方法:

对这样的系统施加压力的最著名的测试用例是在 NFS 上安装根文件系统启动 Linux,然后在本地构建一些更大的软件包(例如,在系统上编译 Linux 内核)——这将导致足够的上下文切换,网络流量(以及因此来自网络控制器的 DMA 传输)、不同的 RAM 使用等来触发该区域的任何薄弱环节。

在构建 linux 内核时,您可能对该选项感兴趣,该CONFIG_MEMTEST=y选项会导致构建内置内存测试。这曾经仅适用于 x86 架构,但我相信最近的版本也支持它在其他架构上,甚至可能是 ARM。

memtester工具已经在一些 Linux 发行版构建并可用,适用于各种架构,包括 ARM。

kernel-memtest项目可能也会让您感兴趣。

请记住,没有工具可以测试它正在运行的内存(因此正在运行的操作系统中的程序将有很大的盲点),并且基本的读/写测试不会揭示每种类型的缺陷或其他错误。相应地设置您的期望,如果您有理由怀疑记忆力不好,请考虑尝试几种不同的测试工具。

于 2020-08-16T22:42:51.883 回答
0

截至 2021 年 2 月,有一个基于 ARM 的MemTest86版本。它与 x86 磁盘映像在同一个包中。

但是,您需要一台带有 UEFI BIOS 的机器来启动它。因此,在大多数台式机和服务器级机器上都可以,但在没有内置 BIOS 的基于 ARM 的小型设备上则不行。

于 2021-02-10T05:44:12.270 回答