我正在嘗試在匯編中撰寫裸機代碼并使用 GCC 工具鏈編譯 鏈接它。據我所知,正確的步驟是遵循以下步驟:
- 重啟后 - MCU 必須檢查向量表并執行重置處理程式,在那里我初始化堆疊指標。
- 執行主代碼。為了完成這個任務,我還需要有各自的聯結器腳本。當我嘗試執行聯結器時,它會引發語法錯誤。請指教:
- 鏈接描述檔案中必須更正的內容
- 正確的 vtable 和處理程式執行順序。
代碼:
stack_size = 0x400
stack_start = 0x20000000 stack_size
gpiob_base = 0x40010C00
rcc_base = 0x40021000
rcc_apb2enr = rcc_base 0x18
gpio_crl = gpiob_base
gpiob_odr = gpiob_base 0x0C
.syntax unified
.cpu cortex-m3
.thumb
.global main
.global vtable
main:
LDR R0, =rcc_apb2enr
LDR R1, [R0]
LDR R2, =0x8 // Activate 3rd bit in registry
ORR R1, R2
STR R1, [R0]
// Configure GPIO_CRL
LDR R0, =gpio_crl
LDR R1, [R0]
LDR R2, =0xFFFFFF00
AND R1,R1,R2
ORR R1, R1, #0x20
STR R1, [R0] // Reset register
//Configure GPIOB_ODR
LDR R0, =gpiob_odr
LDR R1, [R0]
ORR R1, #0x2
STR R1, [R0]
B .
vtable:
.word stack_start
.word reset_handler
reset_handler:
B main
鏈接腳本:
/* - STM32F103C8T6 - Medium Density device
* - RAM: 20K, Flash:64K CPU: 72MHz
*/
ENTRY(reset_handler);
MEMORY {
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
}
SECTIONS
{
/* Section that stores program instructions (code) */
.text : {
. = ALIGN(4);
KEEP(*(.vtable))
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} > FLASH
_data_flash = .;
// Section that store initialized data - variables
.data : AT(_data_flash){
. = ALIGN(4);
_data_begin = .;
*(.data)
*(.data*)
. = ALIGN(4);
_data_end = .;
} > RAM
/* Section that stores uninitialized data */
.bss :{
_bss_begin = .;
_bss_start_ = _bss_begin;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
_bss_end_ = _bss_end;
} > RAM
/* Here we define stack */
_stack_size = 1024;
_stack_end = ORIGIN(RAM) LENGTH(RAM);
_stack_begin = _stack_end - _stack_size;
. = _stack_begin;
._stack :{
. = . _stack_size;
} > RAM
}
._stack :{
. = . _stack_size;
} > RAM
}
程式拆解:
pi@mylab:~/assembly $ arm-none-eabi-objdump --disassemble bp.o
bp.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
0: 480d ldr r0, [pc, #52] ; (38 <reset_handler 0x4>)
2: 6801 ldr r1, [r0, #0]
4: f04f 0208 mov.w r2, #8
8: ea41 0102 orr.w r1, r1, r2
c: 6001 str r1, [r0, #0]
e: 480b ldr r0, [pc, #44] ; (3c <reset_handler 0x8>)
10: 6801 ldr r1, [r0, #0]
12: f06f 02ff mvn.w r2, #255 ; 0xff
16: ea01 0102 and.w r1, r1, r2
1a: f041 0120 orr.w r1, r1, #32
1e: 6001 str r1, [r0, #0]
20: 4807 ldr r0, [pc, #28] ; (40 <reset_handler 0xc>)
22: 6801 ldr r1, [r0, #0]
24: f041 0102 orr.w r1, r1, #2
28: 6001 str r1, [r0, #0]
2a: e7fe b.n 2a <main 0x2a>
0000002c <isr_vector>:
2c: 20000400 .word 0x20000400
30: 00000034 .word 0x00000034
00000034 <reset_handler>:
34: f7ff bffe b.w 0 <main>
38: 40021018 .word 0x40021018
3c: 40010c00 .word 0x40010c00
40: 40010c0c .word 0x40010c0c
uj5u.com熱心網友回復:
對于你正在做的事情,你可以從更簡單的開始。
flash.s
stack_size = 0x400
stack_start = 0x20000000 stack_size
gpiob_base = 0x40010C00
rcc_base = 0x40021000
rcc_apb2enr = rcc_base 0x18
gpio_crl = gpiob_base
gpiob_odr = gpiob_base 0x0C
.syntax unified
.cpu cortex-m3
.thumb
vtable:
.word stack_start
.word reset_handler
.thumb_func
reset_handler:
B main
main:
LDR R0, =rcc_apb2enr
LDR R1, [R0]
LDR R2, =0x8 // Activate 3rd bit in registry
ORR R1, R2
STR R1, [R0]
// Configure GPIO_CRL
LDR R0, =gpio_crl
LDR R1, [R0]
LDR R2, =0xFFFFFF00
AND R1,R1,R2
ORR R1, R1, #0x20
STR R1, [R0] // Reset register
//Configure GPIOB_ODR
LDR R0, =gpiob_odr
LDR R1, [R0]
ORR R1, #0x2
STR R1, [R0]
B .
閃存檔案
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
}
建造
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m3 flash.s -o flash.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy -O binary so.elf so.bin
檢查(應始終為新專案執行此操作)
so.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <vtable>:
8000000: 20000400 andcs r0, r0, r0, lsl #8
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset_handler>:
8000008: e7ff b.n 800000a <main>
0800000a <main>:
800000a: 480b ldr r0, [pc, #44] ; (8000038 <main 0x2e>)
800000c: 6801 ldr r1, [r0, #0]
800000e: f04f 0208 mov.w r2, #8
8000012: ea41 0102 orr.w r1, r1, r2
8000016: 6001 str r1, [r0, #0]
...
因此,只需將向量表放在正確的位置,并且重置處理程式地址是正確的(地址或紅色),就有一半的機會可以作業。
還可以看到它正在生成拇指 2 代碼(如果你最終使用 cortex-m0 并且不修復你的構建/代碼,最容易從適用于所有它們的 cortex-m0 開始,然后如果需要選擇拇指 2。YMMV )
now if you had other objects the one with the vector table, flash.o in this case, would need to be the first object on the command line to be the first .text to be parsed and placed in the binary.
You can complicate things to mark a special section for the vector tables (note you call sections whatever you want with some limitations, do not have to call it vectors or vector_table, etc unless you want). You will then need to add more linker stuff and more code, in the source, etc. Since you have to get the right stuff on the command line to start with and you have to put the work in to get the code right including directives. Why create more work that adds no value, just put the vector table in the right place, near the reset handler. YMMV.
So you have your vector table near the end of the code, not the first thing. Basically you asked for the table to be in the wrong place. And it is. You need it first to fit in with the rest of this code. Next since you are referencing the address to the reset handler in the table, you need the function address not just the address, you need to declare that label as a function for this to work for thumb/arm. For thumb functions you can use the shortcut .thumb_func somewhere before the label (does not have to be the line before) it will trigger the next label the gnu assembler finds as a thumb function. Because this is all a single file under a single .thumb near the top the branch to main is okay. Ideally you might want to declare that a function too, certainly if you are doing arm/thumb interwork for a non-cortex-m arm you need to do this in your global asm functions.
適用于 arm 和拇指 gnu 匯編程式的另一種方法是
.type functionname, %function
functionname:
對于此任務,您的鏈接描述檔案過于復雜。我相信你正在努力解決這個復雜問題。
您使用了正確的地址,但您反匯編了物件而不是精靈。但是根據您的代碼,它仍然會構建錯誤。
您在聯結器腳本中宣告了一個堆疊(我傾向于滿懷熱情地討厭它,但有些人喜歡它,YMMV)。但是您沒有在向量表中使用該鏈接描述檔案變數,而是使用了計算值。這個程式沒有壞,但有一點需要注意。
堆疊由向量表設定,因此您可以使用它(可以呼叫函式)。我建議
bl main
b .
在重置處理程式中,然后 main 可以選擇無限回圈或回傳,你是安全的/很好。
如果您沒有在向量表中正確設定堆疊地址,那么您可能會在那里遇到麻煩。
注意 odr 很好,但您可能想查看 bsrr 暫存器。對于單個埠位更靈活。并且打開該位并不會打開所有板上的 LED,有些 gpio 連接到另一端,然后您將其接地以打開它。所以請注意這一點并查看原理圖或檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/392655.html
上一篇:GNU匯編器沒有給出正確的浮點值
下一篇:用于鎖定或的C內置或行內匯編
