i.MX35 приостановить процессор и DDR2 от IRAM
Мне нужно перевести мое устройство в режим очень низкого энергопотребления из 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 в режим отключения при предварительной зарядкевыполнить команду precharge all и получить доступ к памяти с максимумом A10 (например, 0x400), чтобы эффективно закрыть все банкиперевести процессор в режим ожидания, выполнив инструкцию WFIзатем снова включите все (оставлено в исходном коде ниже)Соответствующий код выглядит так:
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)
Проблема в том, что доступ к ОЗУ осуществляется с помощью фиктивной записи. Это просто приводит к исключению сбоя данных, а затем ЦП теряется. Если я пропущу эту часть, DDR2, похоже, не будет переведен в режим низкого энергопотребления, потому что потребление тока не снижается.
Теперь я полностью застрял и потерял идею здесь. Может кто-нибудь дать мне подсказку, что я делаю неправильно или чего мне здесь не хватает? Или есть какая-либо документация или исходный код, демонстрирующий всю процедуру для i.MX35 в Linux?