汇编程序未清除我的树莓派 4 上的 GPIO 引脚

问题描述 投票:0回答:1

怎么样,我想几个月后我会回到这个问题,我在 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 上的偏移量,尽管数据表说这是偏移量,但它不起作用。

embedded-linux arm64 gpio raspberry-pi4 device-driver
1个回答
0
投票

这里有一个错误:

    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
来查看系统调用实际上是由您的程序进行的。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.