首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >退出DRAM中的Linux以运行SRAM中的裸金属代码。

退出DRAM中的Linux以运行SRAM中的裸金属代码。
EN

Stack Overflow用户
提问于 2016-06-28 17:17:58
回答 2查看 704关注 0票数 1

没有详细信息的问题:

是否有可能将从Linux运行的裸金属可执行文件复制到处理器内部的SRAM中并运行?此应用程序将暂停DDR并禁用电源线路以修复硬件问题。

详细信息:

我正在开发一个使用ARM处理器并运行嵌入式Linux的定制嵌入式产品。处理器是Atmel ATSAMA5D36。我们使用以下辅助引导程序和内核:

当前的引导过程大致如下:

  • Atmel有一个ROM引导加载程序,它可以在NOR闪存上找到我们的引导加载程序,并将其复制到SAMA5 5的内部SRAM中。
  • 第二级引导加载程序初始化硬件,并在LPDDR中复制/解压内核。
  • 我们跳入内核,运行LPDDR中的linux。

该设备以两种方式工作:连接主电源或由电池备份。当连接到主电源时,可以发出命令来挂起linux,这会使LPDDR内存进入自刷新模式。一旦LPDDR处于自刷新状态,主电源可以被移除,并且LPDDR将持续到下一个电源启动周期。在板上有一个小型的二级ARM Cortex-M0微控制器,它可以一直运行,并执行IO处理和其他一些与时间相关的任务。

问题:

当主电源从板上移除时,电池切换到LPDDR,二级ARM微控制器,主SAMA5电源下降。当电源从SAMA5上移除,电源盖放电时,处理器(100 is )会短暂地熄灭,并迫使IO在永久关闭之前进入复位状态。不幸的是,这个“点”在电源拉高的LPDDR CKE线足够长,使LPDDR退出自刷新模式。这会导致LPDDR上的内存损坏。

显示主电源电压和DDR_CKE信号的范围图:

要解决这个问题,我们需要挂起LPDDR,然后告诉PMIC禁用处理器上的DDR_IO供应( DDR的IO供应和主供应是分开的)。这将防止从自我刷新中弹出LPDDR的电源点。不幸的是,这是一个鸡或蛋的问题。如果我们挂起LPDDR,我们就不能运行任何代码来与PMIC通信并禁用特定的供应。如果我们禁用供应,我们就不能再与LPDDR通信,将其放入自刷新中。

当前的解决方案:

当发出命令来挂起主处理器时,它会将其转发给辅助微控制器,然后将LPDDR挂起以进行自刷新。二级微控制器然后重置主处理器并等待辅助引导加载程序的出现。启动加载程序时,它将与微控制器检查是否发出暂停。如果是的话,它会让LPDDR进行自我刷新,告诉PMIC (通过I2C)禁用DDR_IO电源,并在一段时间内(1)等待电力被移除。

问题是启动时间-它需要120毫秒从重置到DDR init和挂起。LPDDR有一个16-64ms的刷新周期,因此我们至少缺少一个DDR的刷新周期。到目前为止,在测试中,我们还没有看到由于这种延迟而导致内存损坏,但是这显然是一个不太理想的解决方案(但比硬件版本更好)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-01 00:20:05

只是回过头回答这个问题。实际上,将代码从DRAM加载到SRAM并执行它是可能的。经过进一步的研究,我们发现许多嵌入式平台使用这种方法来处理电源管理功能,特别是挂起/恢复--就像我在这里试图解决的问题一样。

下面是linux如何在at91平台上处理进入挂起:http://lxr.free-electrons.com/source/arch/arm/mach-at91/pm.c#L416

我们需要一个定制的实现,并最终创建了一个使用相同方法的内核模块。然后我们从用户土地插入内核模块,它为我们提供了一种从SRAM运行代码以执行我们的电源管理功能的方法。

示例内核模块代码:

代码语言:javascript
复制
#include <linux/io.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#define VIRT_BASE 0xFEF78000 //for AT91

static void (*sram_fn)(void) = NULL;

unsigned char buf[] = {
    //your complied ARM byte code
};

static void __init init_sram_fn (void)
{
    sram_fn = (void *) (VIRT_BASE – sizeof(buf));
    memcpy(sram_fn, &buf, sizeof(buf));
    sram_fn();
}

static void __exit cleanup_sram_fn (void){}

module_init(init_sram_fn);
module_exit(cleanup_sram_fn);

从用户土地调用

代码语言:javascript
复制
system("insmod custom_pm_module.ko");
票数 1
EN

Stack Overflow用户

发布于 2016-06-28 20:07:10

是否有可能将从Linux运行的裸金属可执行文件复制到处理器内部的SRAM中并运行?

这是从非常困难到不可能的,取决于你的平台。Linux内核本身是从DRAM运行的,所以当DRAM关闭时,您将没有活动的linux内核和任何OS服务(没有syscalls、没有调度程序、没有irqs/irq处理程序;如果在dram中没有irq向量?)。

您的芯片只有128 KB的SRAM:http://www.atmel.com/devices/ATsama5d36.aspx?tab=parameters -它只是小到包含完整的Linux内核。

因此,您可以尝试创建一些可执行文件,将其优先级更改为RT (实时),以便能够忽略调度程序/irqs.您应该将此可执行文件完全放入SRAM (只有当SRAM可用作直接寻址内存时).您还应该检查当需要时,它是否会被加载(或者应该让可执行文件一直运行在核心上?)是多核芯片吗?)

如果不是作为可执行文件编写,而是作为内核的一部分编写,会容易一些.任务看起来还是不可能的..。

在关闭DRAM之前,DRAM和CPU运行的时间是什么时候?

DRAM可以保存几个刷新周期的数据;它将保存大部分数据几秒钟(冷却时间更长- attack;热时更短)。您可能需要添加一些数据校验和..。(您的芯片没有用于DRAM的ECC?)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38082488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档