【发布时间】:2014-02-14 12:37:51
【问题描述】:
我必须从 Linux 2.6.38 将我的设备置于非常低功耗模式,因此,有必要暂停所有组件,包括 CPU 和 DDR2。
到目前为止,我发现我必须将核心汇编函数复制到处理器的内部存储器中并从那里执行它。基本上,它看起来像这样:
cpaddr = iram_alloc(SZ_1K, &iram_addr);
if(!cpaddr) return -ENOMEM;
suspend_iram_base = __arm_ioremap(iram_addr, SZ_1K, MT_HIGH_VECTORS);
memcpy(suspend_iram_base, cpu_v6_sdram_off, SZ_1K);
flush_icache_range(suspend_iram_base, suspend_iram_base + SZ_1K);
flush_cache_all();
__asm__ __volatile__(
"ldr r0, %0\n"
"ldr r1, %1\n"
"ldr r2, %2\n"
"blx r2\n"
"nop\n"
: : "m" (esdctl_addr),
"m" (csd0_addr),
"m" (suspend_iram_base));
到目前为止,一切都按预期工作,我可以使用 JTAG 调试器从内部存储器(在虚拟地址空间中)验证代码执行。
如果我理解正确的话,我必须在 IRAM 函数中执行以下操作:
- 禁用中断和缓存
- 将 SDRAM 控制器设置为预充电断电模式
- 执行预充电所有命令并以 A10 为高电平(例如 0x400)访问内存以有效关闭所有银行
- 通过执行 WFI 指令使 CPU 进入待机状态
- 之后重新启用所有内容(在下面的源代码中省略)
对应的代码如下:
ENTRY(cpu_v6_sdram_off)
@ r0: esdctl base address
@ r1: csd0 address with a10 high
cpsid if
@ disable I and D cache
mrc p15, 0, r2, c1, c0, 0
bic r2, r2, #0x00001000 @ disable I cache
bic r2, r2, #0x00000004 @ disable D cache
mcr p15, 0, r2, c1, c0, 0
@ invalidate I cache
mov r2, #0
mcr p15, 0, r2, c7, c5, 0
@ clear and invalidate D cache
mov r2, #0
mcr p15, 0, r2, c7, c14, 0
@ precharge power down mode
ldr r2, [r0]
bic r2, r2, #0xc00
orr r2, r2, #0x400
str r2, [r0]
@ precharge all command
mov r2, #0x92
lsl r2, #24
orr r2, r2, #0x228000
orr r2, r2, #0x0400
str r2, [r0]
mov r2, #0x12
lsl r2, #24
orr r2, r2, #0x340000
orr r2, r2, #0x5600
orr r2, r2, #0x78
str r2, [r1] @ dummy write access
@ execute wait for interrupt
mov r1, #0
mcr p15, 0, r1, c7, c10, 4
mcr p15, 0, r1, c7, c0, 4
cpsie if
bx lr
ENDPROC(cpu_v6_sdram_off)
问题在于使用虚拟写入访问 RAM。它只会导致数据中止异常,然后 CPU 就会丢失。 如果我不考虑这部分,DDR2 似乎并没有进入低功耗模式,因为电流消耗并没有下降。
现在我完全被困在这里,没有想法。有人可以给我一个提示我做错了什么或我在这里缺少什么吗? 或者是否有任何可用的文档或源代码演示 Linux 上 i.MX35 的整个过程?
【问题讨论】: