gpt4 book ai didi

c - 将 C 代码编译为裸机(树莓派)时我做错了什么?

转载 作者:太空宇宙 更新时间:2023-11-04 03:22:35 25 4
gpt4 key购买 nike

我花了好几天时间试图解决这个问题,但我就是做不到。我有一些C代码。我已经为这个 C 程序制作了汇编代码,将汇编复制粘贴到其他人的项目(只包含一个汇编文件)并进行汇编。在这些情况下,一切正常。但是,如果我尝试直接从 C 编译以生成二进制文件,那是行不通的。即使其他一切都应该相同。这是我的 C 代码:

 #include <stdint.h>

#define REGISTERS_BASE 0x3F000000
#define MAIL_BASE 0xB880 // Base address for the mailbox registers
// This bit is set in the status register if there is no space to write into the mailbox
#define MAIL_FULL 0x80000000
// This bit is set in the status register if there is nothing to read from the mailbox
#define MAIL_EMPTY 0x40000000

struct Message
{
uint32_t messageSize;
uint32_t requestCode;
uint32_t tagID;
uint32_t bufferSize;
uint32_t requestSize;
uint32_t pinNum;
uint32_t on_off_switch;
uint32_t end;
};

struct Message m =
{
.messageSize = sizeof(struct Message),
.requestCode =0,
.tagID = 0x00038041,
.bufferSize = 8,
.requestSize =0,
.pinNum = 130,
.on_off_switch = 1,
.end = 0,
};

/** Main function - we'll never return from here */
int _start(void)
{
uint32_t mailbox = MAIL_BASE + REGISTERS_BASE + 0x18;
volatile uint32_t status;

do
{
status = *(volatile uint32_t *)(mailbox);
}
while((status & 0x80000000));

*(volatile uint32_t *)(MAIL_BASE + REGISTERS_BASE + 0x20) = ((uint32_t)(&m) & 0xfffffff0) | (uint32_t)(8);

while(1);
}

这是我从成功方法中复制的链接器文件:

/*
* Very simple linker script, combing the text and data sections
* and putting them starting at address 0x800.
*/
SECTIONS {
/* Put the code at 0x80000, leaving room for ARM and
* the stack. It also conforms to the standard expecations.
*/
.init 0x8000 : {
*(.init)
}

.text : {
*(.text)
}

/* Put the data after the code */
.data : {
*(.data)
}
}

这就是我编译和链接所有内容的方式:

arm-none-eabi-gcc -O0 -march=armv8-a PiTest.c -nostartfiles -o kernel.o
arm-none-eabi-ld kernel.o -o kernel.elf -T kernel.ld
arm-none-eabi-objcopy kernel.elf -O binary kernel.img

我的目标架构是 armv8,因为那是 pi model 3 使用的架构。我不知道生成的程序集是如何工作的,但 C 代码直接没有。请帮助我处于疯狂的边缘。

编辑:预期的行为是 pi 的灯亮起。它与我描述的第一种方法一起使用。使用第二种方法,灯保持关闭状态。

EDIT4:对文件进行了一些更改,删除了以前使用过时信息进行的编辑以减少帖子大小

  kernel.elf:     file format elf32-littlearm


Disassembly of section .init:

00008000 <_start>:
8000: e3a0dd7d mov sp, #8000 ; 0x1f40
8004: eaffffff b 8008 <kernel_main>

Disassembly of section .text:

00008008 <kernel_main>:
8008: e52db004 push {fp} ; (str fp, [sp, #-4]!)
800c: e28db000 add fp, sp, #0
8010: e24dd00c sub sp, sp, #12
8014: e30b3898 movw r3, #47256 ; 0xb898
8018: e3433f00 movt r3, #16128 ; 0x3f00
801c: e50b3008 str r3, [fp, #-8]
8020: e51b3008 ldr r3, [fp, #-8]
8024: e5933000 ldr r3, [r3]
8028: e50b300c str r3, [fp, #-12]
802c: e51b300c ldr r3, [fp, #-12]
8030: e3530000 cmp r3, #0
8034: bafffff9 blt 8020 <kernel_main+0x18>
8038: e30b38a0 movw r3, #47264 ; 0xb8a0
803c: e3433f00 movt r3, #16128 ; 0x3f00
8040: e3082050 movw r2, #32848 ; 0x8050
8044: e3402001 movt r2, #1
8048: e3c2200f bic r2, r2, #15
804c: e3822008 orr r2, r2, #8
8050: e5832000 str r2, [r3]
8054: eafffffe b 8054 <kernel_main+0x4c>

Disassembly of section .data:

00008058 <__data_start>:
8058: 00000020 andeq r0, r0, r0, lsr #32
805c: 00000000 andeq r0, r0, r0
8060: 00038041 andeq r8, r3, r1, asr #32
8064: 00000008 andeq r0, r0, r8
8068: 00000000 andeq r0, r0, r0
806c: 00000082 andeq r0, r0, r2, lsl #1
8070: 00000001 andeq r0, r0, r1
8074: 00000000 andeq r0, r0, r0

Disassembly of section .ARM.attributes:

00000000 <_stack-0x80021>:
0: 00002e41 andeq r2, r0, r1, asr #28
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 00000024 andeq r0, r0, r4, lsr #32
10: 412d3805 ; <UNDEFINED> instruction: 0x412d3805
14: 070e0600 streq r0, [lr, -r0, lsl #12]
18: 09010841 stmdbeq r1, {r0, r6, fp}
1c: 14041202 strne r1, [r4], #-514 ; 0xfffffdfe
20: 17011501 strne r1, [r1, -r1, lsl #10]
24: 1a011803 bne 46038 <__bss_end__+0x3dfc0>
28: 2a012201 bcs 48834 <__bss_end__+0x407bc>
2c: Address 0x000000000000002c is out of bounds.


Disassembly of section .comment:

00000000 <.comment>:
0: 3a434347 bcc 10d0d24 <_stack+0x1050d03>
4: 35312820 ldrcc r2, [r1, #-2080]! ; 0xfffff7e0
8: 392e343a stmdbcc lr!, {r1, r3, r4, r5, sl, ip, sp}
c: 732b332e ; <UNDEFINED> instruction: 0x732b332e
10: 33326e76 teqcc r2, #1888 ; 0x760
14: 37373131 ; <UNDEFINED> instruction: 0x37373131
18: 2029312d eorcs r3, r9, sp, lsr #2
1c: 2e392e34 mrccs 14, 1, r2, cr9, cr4, {1}
20: 30322033 eorscc r2, r2, r3, lsr r0
24: 35303531 ldrcc r3, [r0, #-1329]! ; 0xfffffacf
28: 28203932 stmdacs r0!, {r1, r4, r5, r8, fp, ip, sp}
2c: 72657270 rsbvc r7, r5, #112, 4
30: 61656c65 cmnvs r5, r5, ror #24
34: 00296573 eoreq r6, r9, r3, ror r5

最佳答案

kernel8.img

12345678
00000800
00080264
00000000
12345678

kernel8-32.img

12345678
00008320
00008224
200001DA
12345678

kernel7.img

12345678
00000700
00008224
200001DA
12345678

kernel.img

12345678
00000000
00008224
200001DA
12345678

当我编写并发布此代码时,这就是我得到的结果,因此如果您将文件命名为 kernel.img,那么 0x8000 是您的入口点,我在您的其他 SO 问题中给出的答案是一个完整的 raspberry pi 起点。您可以简单地添加您的邮箱内容,但如果您为此苦苦挣扎,我觉得邮箱和视频不是您应该开始 IMO 的地方。

如果您将文件命名为 kernel8.img,则入口点为 0x80000,更改链接描述文件以匹配。

我有一个基于串行端口的引导加载程序,你可以用它来保存 sd 卡上的舞曲,可以用它走很长的路,然后在你的应用程序运行后简单地使用你正在创建的二进制版本写入闪存。

编辑

好吧,这太恶心了,把它贴在这里也许意味着你不能在你的类作业中使用它……你真的应该正确地做这件事,而不是在你的 Bootstrap 中使用内联汇编……

所以.c

asm(
".globl _start\n"
"_start:\n"
"mov sp,#0x8000\n"
"bl centry\n"
"b .\n"
);


unsigned int centry ( void )
{
return(5);
}

build

arm-none-eabi-gcc -O2 -c so.c -o so.o
arm-none-eabi-ld -Ttext=0x8000 so.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf -O binary kernel.img

检查

Disassembly of section .text:

00008000 <_start>:
8000: e3a0d902 mov sp, #32768 ; 0x8000
8004: eb000000 bl 800c <centry>
8008: eafffffe b 8008 <_start+0x8>

0000800c <centry>:
800c: e3a00005 mov r0, #5
8010: e12fff1e bx lr

一个完整的 raspberry pi C 和 Bootstrap 示例,可以在任何 pi 上运行(据我所知,他们可能在过去几个月更改了 GPU 引导加载程序,但假设没有)。

关于c - 将 C 代码编译为裸机(树莓派)时我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44123055/

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