怎么样,我想几个月后我会回到这个问题,我在 ARM64 组件中为树莓派 4 制作了一个 gpio 驱动程序,但是 clr0 偏移量无法让我闪烁 LED,这是代码。
.global _start
.equ RDWR, 00000002
.equ SYNC, 00010000
.equ RESOLVE_IN_ROOT, 0x08
.equ MAP_SHARED, 0x01
.equ PROT_READ, 0x1
.equ PROT_WRITE, 0x2
.equ PAGELEN, 4096
.equ offset17, 21
.equ GPFSEL1, 0x04
.equ GPSET0, 0x1c
.equ GPCLR0, 0x28
_start:
ldr x0, =RESOLVE_IN_ROOT /* Means you want to access another directory starting from root */
ldr x1, =devmem /* The pathname for devmem as a zero placed string */
mov x2, #(RDWR+SYNC) /* Read, and Write flags plus Sync to enable i/o operations of the returned file descriptor */
mov x8, #0x38
svc 0
adds x4, xzr, x0 /* The returned file descriptor */
bpl Mmap
mov x0, #1
ldr x1, =errmessage
ldr x2, =len
mov x8, #0x40
svc 0
b exit
Mmap:
ldr x0, =gpioBaseAddress /* The base address for the gpio pins */
mov x1, #PAGELEN /* Page length, which is 4096 */
mov x2, #(PROT_READ + PROT_WRITE) /* Pages may be Read, and Written */
mov x3, #MAP_SHARED /* Updates to the mapping are visible to the other processes mapping the same region */
/* adds x4, xzr, x0 from the openat function, so the returned file descriptor from opening dev/gpiomem */
orr x5, x5, xzr /* We dont need this parameter, so just put 0 */
mov x8, #0xde
svc 0
adds x9, xzr, x0 /* The returned file descriptor of the virtual page of memory created at the mapped address of 0xfe200000 */
bpl Select
mov x0, #1
ldr x1, =errmessage
mov x2, #len
mov x8, #0x40
svc 0
Select:
mov x1, #0b001
lsl x1, x1, #offset17
str w1, [x9, #GPFSEL1] /* Each instruction interacting with the gpio pins has to be 32 bit, or else you will recieve a bus error, store the 3 bit value in x1 in the gpfsel1 offset address to set pin17 as an output */
loop:
add x10, x10, #1
mov x1, #1
str w1, [x9, #GPSET0]
ldr x0, =timeamount
ldr x1, =timeremaining
mov x8, #0x65
svc 0
str w1, [x9, #GPCLR0]
mov x0, =timeamount
mov x1, =timeremaining
mov x8, 0x65
svc 0
cmp x10, #10
bne loop
b exit
exit:
mov x0, #0
mov x8, #0x5d
svc 0
.data
devmem:
.asciz "/dev/gpiomem"
errmessage:
.asciz "couldn't obtain file descriptor"
len = .-errmessage
gpioBaseAddress:
.word 0xfe200000
timeamount:
.word 1
timeremaining:
.word 0
我尝试更改 GPCLR0 上的偏移量,尽管数据表说这是偏移量,但它不起作用。
这里有一个错误:
ldr x0, =gpioBaseAddress
gpioBaseAddress:
.word 0xfe200000
伪指令
ldr x0, =foo
将x0
的值加载到foo
。 但这里gpioBaseAddress
是一个标签,所以它的值就是标签的地址。
如果您确实想要
0xfe200000
中的值 x0
,则必须再次加载:
ldr x0, =gpioBaseAddress
ldr w0, [x0] // w0 because gpioBaseAddress is .word which is 32 bits
但更好的方法是将其定义为常量,而不是内存中的数据对象:
.equ gpioBaseAddress 0xfe200000
ldr x0, =gpioBaseAddress
您拨打
nanosleep
时遇到另一个问题。 每个参数都应该是指向由两个 64 位元素组成的 struct timespec
的指针,但它们仅指向单个 32 位元素。
如果您有更多错误(这是很有可能的),您应该通过使用调试器(例如
gdb
)单步执行来调查它们,检查寄存器和内存内容,以及使用strace
来查看系统调用实际上是由您的程序进行的。