gpt4 book ai didi

linux - i.MX35 从 IRAM 挂起 CPU 和 DDR2

转载 作者:太空狗 更新时间:2023-10-29 12:16:49 25 4
gpt4 key购买 nike

我必须让我的设备从 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 Controller 设置为预充电断电模式
  • 执行预充电所有命令并使用 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 的整个过程?

最佳答案

除了禁用 icachedcache 外,还需要清空所有缓冲区。我只在 IMX25 上实现过这个;它是一个 ARM926 (armv5)。我现在正在为 armv7 开发,似乎 dcache 刷新可能是合适的。即,确保 CPU 将所有内容转储到 SDRAM。

现在,您似乎还错过了关闭 MMU 的关键步骤。当您运行 str r2, [r1] @dummy write access 时,您将遇到 TLB 未命中并尝试访问可能位于 SDRAM 中的页表。我看到一个问题 ;-)。幸运的是,您拥有与 PC 相关的汇编程序,可以随时随地运行。

这是一个在实际调用例程之前禁用 MMU 的示例函数。它适用于 ARMV5,您需要将 p15 值更新为您的 CPU 的等效功能。

static void phys_execute(void /*@unused@*/ (*function_pointer)(void))
{
__asm volatile (
" push {r4-r12,lr} \n" /* save everything */
"1: mrc p15, 0, r15, c7, c14, 3 \n" /* armv5 specific.. */
" bne 1b \n" /* dcache clean */
" mov r8, #0 \n"
" mcr p15, 0, r8, c7, c5, 0 \n" /* invalidate icache */
" mcr p15, 0, r8, c7, c10, 4 \n" /* drain wb armv5 */
" mrc p15, 0, r10, c1, c0, 0 \n" /* caches/mmu off */
" bic r8, r10, #0x5 \n"
" bic r8, r8, #0x1000 \n"
" mcr p15, 0, r8, c1, c0, 0 \n"
" blx r0 \n" /* Call r0 */
" mcr p15, 0, r10, c1, c0, 0 \n" /* caches on..*
"1: mrc p15, 0, r15, c7, c14, 3 \n" /* armv5 again */
" mov r8, #0 \n"
" bne 1b \n"
" mcr p15, 0, r8, c7, c5, 0 \n"
" mcr p15, 0, r8, c7, c10, 4 \n"
" pop {r4-r12,pc} \n"
);
}

r1r2 将进入通过物理 ram 调用的例程。您可以重新调整它以硬编码三个参数,然后将函数指针放入 r4。但是,您的

 @ r0: esdctl base address
@ r1: csd0 address with a10 high

必须更改为物理地址,以便当 cpu_v6_sdram_off 运行时,它将访问非虚拟地址。

关于linux - i.MX35 从 IRAM 挂起 CPU 和 DDR2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21779633/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com