- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在构建一个运行在arm cortex-m0+微控制器上的软件。它包括一个USB引导加载程序,在调用函数时作为辅助程序运行。编译期间插入memcpy
函数有问题。
背景
链接器脚本是一切的开始。大部分都是直截了当的标准。程序存储在.text
中,并从中执行。.text
中的所有内容都存储在芯片的闪存部分。
奇怪的是引导加载程序运行的部分。为了能够在不重写引导加载器代码的情况下写入所有flash,我的引导加载器入口点将引导加载器程序的副本初始化到微控制器的sram部分,然后从那里执行它。这样,引导加载程序就可以安全地删除设备上的所有闪存,而不会意外地删除自己。
这是通过在链接器脚本中做一个伪造的“覆盖”来实现的(真实的OVERLAY
与我的用例不太匹配):
/**
* The bootloader and general ram live in the same area of memory
* NOTE: The bootloader gets its own special RAM space and it lives on top
* of both .data and .bss.
*/
_shared_start = .;
.bootloader _shared_start : AT(_end_flash)
{
/* We keep the bootloader and its data together */
_start_bootloader_flash = LOADADDR(.bootloader);
_start_bootloader = .;
*(.bootloader.data)
*(.bootloader.data.*)
. = ALIGN(1024); /* Interrupt vector tables must be aligned to a 1024-byte boundary */
*(.bootloader.interrupt_vector_table)
*(.bootloader)
_end_bootloader = .;
}
.data _shared_start : AT(_end_flash + SIZEOF(.bootloader))
{
_start_data_flash = LOADADDR(.data);
_start_data = .;
*(.data)
*(.data.*)
*(.shdata)
_end_data = .;
}
. = _shared_start + SIZEOF (.data);
_bootloader_size = _end_bootloader - _start_bootloader;
_data_size = _end_data - _start_data;
_end_flash
是对上一节末尾的引用,该节将其所有数据存储在flash中(
.text
,
.rodata
,
.init
…基本上任何只读的内容都会被卡在那里)。
.data
和
.bss
部分通常位于ram中。然而,
.bootloader
部分也位于ram中的同一位置。编译时,这两个部分按顺序存储到flash中。在我的
crt0
例程中,
.data
部分从flash复制到ram中相应的地址(由
_start_data
指定),并且
.bss
部分归零。我有一个附加的部分存储在
.text
部分,它通过将flash中的数据复制到ram中来启动引导加载程序,覆盖
.data
和
.bss
中的内容。Bootloader唯一的退出是系统重置,所以它可以破坏正在运行的程序的数据。将引导加载程序复制到ram后,它将执行它。
.data
或
.bss
时出现的问题,我的链接器脚本中有以下三行代码:
NOCROSSREFS(.bootloader .text);
NOCROSSREFS(.bootloader .data);
NOCROSSREFS(.bootloader .bss);
.text
(可能被引导加载程序擦除)、
.data
(引导加载程序位于其上)或
.bss
(引导加载程序再次位于其上)与
.bootloader
部分之间有交叉时,就会发出编译器错误。
bootloader_
函数位于
.bootloader
部分):
20000340 <bootloader_usb_endp0_handler>:
...
20000398: 1c11 adds r1, r2, #0
2000039a: 1c1a adds r2, r3, #0
2000039c: f000 f8e0 bl 20000560 <__memcpy_veneer>
...
20000560 <__memcpy_veneer>:
20000560: b401 push {r0}
20000562: 4802 ldr r0, [pc, #8] ; (2000056c <__memcpy_veneer+0xc>)
20000564: 4684 mov ip, r0
20000566: bc01 pop {r0}
20000568: 4760 bx ip
2000056a: bf00 nop
2000056c: 00000869 andeq r0, r0, r9, ror #16
0x20000000
直到
0xE000000
左右都位于sram中(我在设备上只有4kb的地址)。下面的任何地址都位于flash部分。
0x1fffffc00
部分(
.bootloader
)的函数中,插入了对
bootloader_usb_endp0_handler
(
memcpy
、
2000039c
和
20000562
)的引用,因为我正在执行结构复制等操作。它对
2000056c
的引用位于地址
memcpy
,该地址位于闪存中…可以擦除。
static setup_t last_setup;
last_setup = *((setup_t*)(bdt->addr));
0x00000869
是一个双字结构,
setup_t
是一个
bdt->addr
,我知道它指向的数据看起来像一个
void*
。此行生成对
setup_t
的调用。
memcpy
。。我只想为位于
memcpy
中的引导加载程序模块提供一个特殊的副本。
arm-none-eabi-gcc -Wall -fno-common -mthumb -mcpu=cortex-m0plus -ffreestanding -fno-builtin -nodefaultlibs -nostdlib -O0 -c src/bootloader.c -o obj/bootloader.o
.bootloader
,但我试图摆脱
-Os
。。它不起作用。
最佳答案
我从未尝试过,但您可能会使用EXTERN()
链接器脚本指令来强制加载您的newlibmemcpy()
两次-首先在引导加载程序链接阶段加载到所需的部分,然后取消定义并再次将其链接到“正常”代码中。
关于c - 将memcpy移至另一个代码段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28104672/
我有一个类似于下面给出的 for 循环。 for(int i=0; i<10; i++) { boolean condition = checkCondition(); /* line 3
我有一个循环,处理文件夹的每个文件。万一文件损坏而无法打开,我想: -向用户显示错误消息 -停止执行剩余的代码 -循环到下一个文件 问题是,如果无法在循环开始时打开文件,则仍有许多代码将要执行,这将引
我知道我可以将键绑定(bind)到“移至行首”,但这会忽略缩进。 我正在寻找的是移动到一行文本的开头,以便: CGRect example = CGRectMake(view.frame.origin
我有一个用户请求,我正在努力满足,我能想到的最简单的解释方法是使用图片说明: 本质上,用户正在输入大量日期。而不是输入 MM [反斜杠(或右箭头)] DD [反斜杠] YYYY [反斜杠] 等 ...
我想打开一个 pdf 文件并移动到 C++ 和 qt 程序中的特定书签。根据我的研究,我们可以使用 URL 和命令提示符转到书签。使用 URL 具有特殊格式,如:fileName.pdf#page=3
我正在尝试移至 PHP 记录集中的下一条记录,但遇到了一些问题。 这是我的页面顶部用于设置我的记录集的内容。 $result = mysqli_query($con,"SELECT * FROM
我已经制作了一个在 java 类中运行良好的程序..但是当我将我的代码移动到 servlet 时它并没有像预期的那样运行程序创建一些文件写入它们,然后再从中读取。问题是当我将代码移动到 servlet
我遇到了在 64 位 Windows 上运行的 32 位旧版应用程序的问题。有问题的应用程序使用 CreateFileMapping 创建共享内存。当它在 64 位 Windows 上运行时,任何从另
我们计划迁移到 TFS。虽然我讨厌它,但由于各种原因我们不得不这样做。 我们有开发、暂存和实时分支。我们是否将每个分支的源代码作为单独的文件夹移至 TFS,并稍后将其转换为分支? 是否可以保留历史记录
有人可以为我提供一些关于如何将此代码移植到 renderscript 以获得更好性能的指南吗? private void someMethod() { for (int i = 0; i < src
我有一个非常大的稀疏矩阵,我想将其发送到 Java 函数。我写了一个java代码来完成这个任务,但是它很慢,所以我正在寻找更好的解决方案。我从 R 3 数组发送如下 TMPmat <- as(mySp
我正在移动一张旧的 Mantis table ,上面有 varchar(64) category_id 列添加到新的 Mantis 表中,该表的 int(10) category_id 列。 简化后的
将中等流量网站的所有读取查询从 mysql 移至 solr 是否值得?我们已经使用 solr 作为我们网站的搜索引擎。我们每 24 小时将整个记录加载到 solr 中一次,然后每 20 分钟运行部分导
我在 MySQL (innodb) 中有三个表(X、Y 和 Z)。 X是一个超过1000万行的表,并且以Y为主键作为外键。同样,Z是超过3000万行的表,并且以Y为主键作为外键。 现在的问题是 Y 的
我在没有编程经验的情况下开始探索 Swift2。 我有以下代码在 Playgrounds 中运行良好,使用快速 View 和内联 View 方法。 如何将它与 Storyboard中的实际标签相关联?
在CSAPP练习3.4中 src_t v; dest_t *p; *p = (dest_t) v; 当src_t为char且dest_t为int时,答案为 movsbl %al, (%edx) (v
我正在测试我正在构建的 Webjob 的 Poison 消息处理。 一切似乎都按预期进行,除了一件奇怪的事情: 当一条消息被移动到“-poison”队列时,它的幽灵似乎仍然隐藏在主作业队列中(不可见)
我是 Android/Java 新手,所以请耐心等待。 我从 LoginActivity > onCreate 移动了代码进入我创建的 fragment FragmentLogin方法onCreate
这只是我真实代码的演示,但问题是一样的。有没有其他或更好的解决方案。为什么 animate() 方法不起作用...... $('document').ready(function() { $('p
我有一个小工件。 HTML: X CSS: #it { background: blue; width: 40px; text-align: center; color
我是一名优秀的程序员,十分优秀!