问题标签 [bare-metal]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - AT91 Bootstrap + 裸机应用
我目前正在尝试了解 AT91 和裸机应用程序如何协同工作。我将尝试描述我所拥有的:
- IAR 作为开发环境
- 一个简单的应用程序,我可以通过调试器将其下载到 SRAM 并切换一些 LED(工作!)
- 使用 SAM-BA,我可以将此应用程序写入 SRAM,它会正确启动(LED 正在切换)
- 我的硬件平台是 ATSAMA5D3x-EK
现在我希望这个应用程序首先运行 AT91 引导程序来初始化所有低级硬件(如 DDR-RAM),然后跳转到我的应用程序并运行它。我还没有成功地做到这一点。我可以启动预构建的 uboot 二进制文件,所以我认为不是复制或跳转失败,而是我的应用程序设置不正确。
据我了解,如果我跳转到一个应用程序(我假设这是某种“LDR pc,appstart_address”),地址 appstart_address 处的操作将被执行。
现在,在 ARM 中,前 7 个字节左右是为中止/中断向量保留的,而第一条指令通常是某种“LDR pc,=main”。如果我的应用程序被复制到 RAM 并从那里执行,这些是否需要?我不知何故有一种感觉,将我的应用程序复制到 RAM 后,地址指针不再匹配(尽管它们应该是相对的——这完全正确吗?)
所以我的问题基本上可以归结为:
- AT91 初始化硬件并跳转到我的应用程序后会发生什么
- 我需要以某种特定方式设置我的应用程序吗?我是否需要告诉链接器或任何其他组件它将被重新定位到其他内存位置(at91 引导程序将其复制到 0x2600 0000 而 0x2000 0000 是 DDR 的起始地址)。
- 有谁知道一个很好的教程,它准确地解释了这一步(从 at91 引导程序跳转到我的应用程序)?
我可能可以回答自己的另一个问题:
- 是否可以安全地假设我不需要在我的应用程序开始时执行 board_startup.s 中的指令,这些指令启用浮点单元,设置 sys 堆栈指针等等。我会说硬件本身已经由 AT91 Bootstrap 设置,因此不需要这样的设置。
考虑了几件事后,它归结为:
- 告诉链接器它应该将 main 链接到地址 0x0 是否有意义(因为这是引导程序将跳转到的地方) - 我该怎么做?
c - Intel Galileo 裸机 UART
我想在英特尔伽利略板上编写一个小小的“hello world”裸机应用程序。当然,使用 UEFI 打印文本(到 UART-1)效果很好,但我想“手动”访问 UART,而不需要 UEFI 的任何帮助。
在 QEMU 中,我的代码运行良好:
.h 文件
.c 文件
主要的
规格对我帮助不大。我猜英特尔 Galileo 板上的 UART 不使用/模拟普通/传统 COM 端口 3F8h、2F8h、3E8h 或 2E8h。
谁能告诉我我做错了什么,或者甚至发布一个最小的裸机 hello world 示例?
linker - 将 GMP 链接到裸机程序
我有一些依赖于图书馆的代码,即筑波大学椭圆配对图书馆。这个库本身依赖于 GMP。我想在 ARM 内核上运行这个程序裸机,特别是在 beaglebone black 上。
GMP 是一个庞大的库,所以如果可能的话,我更喜欢交叉编译。除了简单地将整个 GMP 源代码转储到与我的程序相同的文件中并将其推入 arm-none-eabi-gcc 的“蛮力”解决方案之外,我还更喜欢其他方法。
将重要库链接到裸机代码的标准方法是什么?
raspberry-pi - 是否可以在安全模式下启动 Raspberry Pi?
我目前正在我的 Raspberry Pi 上开发一个小型操作系统,我通过替换SD 卡kernel.img
上的文件来安装它。/boot partition
当我的代码运行时,CPU 已经处于正常模式,所以我无法访问 Secure world / Trustzone 区域。
是否可以修改 Raspberry 的启动过程以便能够在安全模式下开始执行我的代码?
最好的,V.
c - 在“C”中的结构元素之间手动插入填充字节
我有一组用于嵌入式应用程序(ARM 裸机)中的外围设备的 32 位寄存器,具有以下字节地址。
CTL 0x0;
STAT 0x4
TXR 0x8 <-- 不连续地址
RXR 0x20
DAT1 0x30 <-- 不连续地址
DAT2 0x40 <-- 不连续地址
等等
我想将所有这些寄存器组合成一个 C 结构(它是一个打包结构)
现在如果我访问
为了获得正确的地址,我手动添加了一些元素
但是根据外围规范,对 RESERVED、RESERVED_1 和 RESERVED_2 的任何访问都会产生错误。
我正在使用 ARM-GCC 工具链。
embedded - AM335x Sitara:如何更改 CPU 模式
我目前正在 TI Sitara AM 3359 上启动一个裸机项目。事实上,我在这个阶段使用 TI 的 ICE 板进行开发。
对于一些外围设备的初始化,我需要切换到特权模式。我想,系统模式就足够了。现在这就是麻烦开始的地方:我如何进入系统模式?
到目前为止我尝试过:
- 覆盖向量表中的指令:
我将_swihandler的地址存储在地址0x4030CE28。ldr r0, _swihandler mov r1, #0xCE28 ; Load global vector table base address, low movt r1, #0x4030 ; Load global vector table base address, high str r0, [r1]
根据 TI 的文档(spruh73h.pdf,技术参考手册),如果执行 0x4030CE08 处的 SWI 指令,则该词将加载到 PC 中。在调试器中,我可以看到存储的值是 0xE92D4001 而不是我的函数实际所在的 0x4030088C。因此,当执行 SWI 时,跳转不起作用。不知道为什么地址写不正确。 - 重定位向量基地址:
我尝试访问 CP15 的 VBAR 寄存器。每次我这样做时,我都会跳转到未定义的异常向量地址。似乎我不允许从用户模式这样做。我想我在这里遇到了某种先有后有的问题。 - 将自制向量表链接到 0x4030CE00:
我最后的努力是尝试将自己的向量表链接到正确的地址并覆盖默认值。不知何故,我找不到 Code Composer Studio v5 的汇编语法来重新定位我的向量表。我浏览了 spnu118l.pdf(TI 的汇编语言工具文档)中列出的汇编器指令,但找不到有用的东西。我是否必须编写分散文件或使用链接器命令行选项?
这篇文章似乎与我的问题有关。
assembly - 如何在 x86_64 上进入 64 位模式
我在 xv6 https://github.com/chrisdew/xv6/blob/master/bootasm.S中找到了一些不错的程序集,它向我展示了如何从 16 位保护模式转移到 32 位保护模式。
有谁知道进入 64 位模式的类似示例?(通过或不使用 32 位模式。)
c++ - C/C++ 裸机编译和针对特定操作系统(Linux)的编译有什么区别?
假设您有一个为 ARM 架构生成二进制文件的交叉编译工具链。
你的工具链是这样的(在带有 Linux 的 X86_64 机器上运行):
- arm-linux-gnueabi-gcc.exe :用于 Linux 的交叉编译,在 ARM 上运行。
- arm-gcc.exe :用于针对 ARM 的裸机交叉编译。
...以及在 ARM 上进行交叉编译的大量其他工具。
我感兴趣的点是:
- (E) 二进制文件之间的 ABI 差异(如果有)
- 裸机情况下的限制(如动态内存分配、在 C++ 情况下使用静态构造函数、线程模型等)
- 两种情况在特定于它们的信息方面的二进制级差异(如调试信息支持等);
assembly - 如何设置 ARM 堆栈帧以便 GDB 可以遍历它?
我正在做一个小项目,在裸机(无操作系统)上为 ARM 使用 Linux 标准 C 库。我使用 qemu-system-arm 作为执行平台,使用 GDB 进行调试。我编写了一个小系统调用处理程序来处理 C 库进行的 SVC 调用,但我感到困惑的是,即使 SVC 处理程序可以,我未处理的系统调用函数也无法将堆栈遍历回调用者。处理程序代码是:
如果我在 __in_syscall 处设置断点,我可以很好地看到堆栈帧。如果我通过分支或间接通过 SVC_Table 中的指针进入 Unhandled_SVC,即使程序正确执行,GDB 也会混淆显示堆栈帧。
我错过了什么?
这是我的ELLCC 嵌入式编译器项目的一部分,完整的源代码在这里。
c++ - 代码使用 g++ 编译,但不使用 arm-none-eabi-g++
我一直在尝试更改一些语法,以强制用户在访问我编写的 STM32F4 Cortex-M4 CPU 的简单库之前启用外围时钟。
在以下代码挣扎了几个小时后,我找不到我做错了什么,并尝试用 linux g++ 编译它,它成功了。
这是关于 ARM g++ 的编译器错误,还是我一直在使用 linux g++ 之前允许我使用的一些非标准行为?
这是一个简化的代码示例:
ARM g++ 输出。
G++ 输出: