4. 案例4

任务说明

本案例基于U-Boot(以qemu-arm或真实开发板为例),完成DDR控制器的时序参数配置与内存初始化,并通过U-Boot自带的内存测试命令验证读写正确性。核心目标是:根据DDR芯片手册中的时序参数(如tRCD、tRP、tRAS等),正确初始化DDR控制器寄存器,使内存可被稳定访问。

环境与依赖

  • U-Boot源码(版本≥2020.01),本案例以qemu-arm板级配置为例
  • 交叉编译工具链:arm-linux-gnueabi-
  • DDR芯片手册中的时序参数表(本案例使用典型值演示)

关键实现

以下代码展示在U-Boot板级初始化文件中配置DDR控制器(以PL330控制器为例)的核心逻辑。实际参数需根据具体芯片手册调整。

// arch/arm/mach-qemu/qemu-arm/ddr_init.c
#include <common.h>
#include <asm/io.h>

/* DDR控制器寄存器基地址(以QEMU虚拟平台为例) */
#define DDR_BASE        0x40000000
#define DDR_CTRL_BASE   0x40001000

/* 时序参数寄存器偏移 */
#define DDR_TIMING0     0x00
#define DDR_TIMING1     0x04
#define DDR_TIMING2     0x08
#define DDR_TIMING3     0x0C
#define DDR_MODE        0x10

/* 从DDR芯片手册获取的时序参数(单位:时钟周期) */
#define DDR_tRCD        3
#define DDR_tRP         3
#define DDR_tRAS        7
#define DDR_tWR         3
#define DDR_tWTR        2
#define DDR_tRRD        2
#define DDR_tRC         (DDR_tRAS + DDR_tRP)

/* 初始化DDR控制器 */
void ddr_controller_init(void)
{
    u32 timing0, timing1, timing2, timing3;

    /* 配置时序参数寄存器 */
    timing0 = (DDR_tRCD << 0) | (DDR_tRP << 8) | (DDR_tRAS << 16);
    timing1 = (DDR_tWR << 0) | (DDR_tWTR << 8) | (DDR_tRRD << 16);
    timing2 = DDR_tRC;
    timing3 = 0; /* 保留 */

    writel(timing0, DDR_CTRL_BASE + DDR_TIMING0);
    writel(timing1, DDR_CTRL_BASE + DDR_TIMING1);
    writel(timing2, DDR_CTRL_BASE + DDR_TIMING2);
    writel(timing3, DDR_CTRL_BASE + DDR_TIMING3);

    /* 使能DDR控制器 */
    writel(0x1, DDR_CTRL_BASE + DDR_MODE);

    /* 等待控制器就绪(轮询状态寄存器) */
    while (!(readl(DDR_CTRL_BASE + 0x14) & 0x1))
        ;

    printf("DDR controller initialized (tRCD=%d, tRP=%d, tRAS=%d)\n",
           DDR_tRCD, DDR_tRP, DDR_tRAS);
}

/* 在板级初始化中调用 */
int board_init(void)
{
    ddr_controller_init();
    return 0;
}

编译与运行

# 编译U-Boot(qemu-arm配置)
make qemu_arm_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- -j4

# 启动QEMU并进入U-Boot命令行
qemu-system-arm -M virt -kernel u-boot -nographic

验证方法

  1. 启动后观察串口输出,应看到DDR controller initialized日志,且无错误信息。
  2. 在U-Boot命令行执行内存测试命令:
# 测试DDR地址范围(假设DDR大小为256MB,起始地址0x40000000)
mw.l 0x40000000 0xdeadbeef 0x1000
cmp.l 0x40000000 0x40000000 0x1000

# 或使用U-Boot自带的内存测试命令
mtest 0x40000000 0x400fffff

通过标准:

  • cmp.l命令无输出(表示数据一致);
  • mtest命令执行完毕显示Tested 1 iteration(s) with 0 errors。

常见问题

  • 初始化后访问异常:检查时序参数是否与芯片手册一致,特别是tRCD和tRP是否满足最小要求。
  • QEMU中无真实DDR模型:本案例使用QEMU虚拟平台,DDR控制器为模拟实现,时序参数仅作演示。在真实硬件上需根据具体芯片手册和控制器型号调整寄存器配置。