在 Raspberry Pi 3 B 型上使用 Assembly 打开 LED

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

我正在尝试使用Assembly点亮连接到GPIO引脚12的LED,我有一个课程作业,我必须使用C和Assembly来实现MasterMind游戏,所以我一直在尝试使用Assembly点亮LED

.section .init
.globl _start
_start:
ldr r0,=0x3F200000 //Base adress from GPIO
 
//Set the GPIO pin 12 as output
mov r1,#1
lsl r1,#6
str r1,[r0,#0x4] // 0x3F200004 is the GPSEL1 Register, where you can choose the function for the pin
 
//prepare the number used for turning the LED off and on
mov r1,#1
lsl r1,#12
 
//main loop, loops all the letters (bl means branch with saving the current physical adress in the link register (lr) so you can jump back to it)
loop$:
 bl morseS
 bl morseO
 bl morseS
b loop$
 
morseS:
 mov r6,lr //move the lr adress to r6 so you dont override it (would be better if implemented with stack)
 bl dotBlink
 bl dotBlink
 bl dotBlink
 bl delayMedium
 mov lr,r6 //move the adress back into the link register
 bx lr
 
morseO:
 mov r6,lr
 bl dashBlink
 bl dashBlink
 bl dashBlink
 bl delayMedium
 mov lr,r6
 bx lr
 
dotBlink:
 mov r7,lr
 str r1,[r0,#0x1C] //this turns the led on (According to the BCM2835 documentation the Register found at 0x3F20001C is GPSET0, so you can turn on the GPIO Pin 12 there
 bl delayShort
 str r1,[r0,#0x28] //this is GPCLR0, so used for turning the pin off again
 bl delayShort
 mov lr,r7
 bx lr
 
dashBlink:
 mov r7,lr
 str r1,[r0,#0x1C]
 bl delayLong
 str r1,[r0,#0x28]
 bl delayShort
 mov lr,r7
 bx lr
 
delayShort: 
 ldr r4,=0x3f003004 //adress for the timer of the raspberry pi
 ldr r4,[r4] //load the value from the timer
 ldr r5,=0x30D40 //200'000 micro seconds in hexadecimal
 delayLoop1$:
  ldr r3,=0x3F003004 
  ldr r3,[r3] //load new timer value
  sub r3,r3,r4 //save time passed since the beginning of subroutine in r3
  cmp r3,r5 //compare 
  blt delayLoop1$ //if difference is smaller than 200ms go to the delay loop again
 bx lr //if time has passed return from function
 
delayMedium:
 ldr r4,=0x3f003004
 ldr r4,[r4]
 ldr r5,=0x61A80
 delayLoop3$:
  ldr r3,=0x3F003004
  ldr r3,[r3]
  sub r3,r3,r4
  cmp r3,r5
  blt delayLoop3$
 bx lr
 
delayLong:
 ldr r4,=0x3f003004
 ldr r4,[r4]
 ldr r5,=0x927C0
 delayLoop2$:
  ldr r3,=0x3F003004
  ldr r3,[r3]
  sub r3,r3,r4
  cmp r3,r5
  blt delayLoop2$
 bx lr

这是我的代码,我认为它看起来不错,我尝试使用编译它

as -o testled.o testled.s
ld -o testled testled.o
sudo ./testled

并且它给出了分段错误,有人可以帮我解决这个问题吗

assembly raspberry-pi arm raspberry-pi3 gpio
1个回答
0
投票

该程序被编写为无需操作系统即可直接访问物理地址空间,但您在配置虚拟内存的 Linux 上运行它。

在 Linux 下,物理地址位于文件

/dev/mem
中,特别是 gpio 寄存器也位于
/dev/gpiomem
中。要使用这些文件,请打开它们,然后您可以使用 mmap 系统调用获取虚拟地址。

例如在C:

fd = open("/dev/mem", O_SYNC | O_RDWR)
gpiobase = mmap(0, 4096 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x3F200000);

但是,我希望尝试像这样访问计时器会导致混乱,因为操作系统将使用计时器。

Linux 还使用

/sys/class/gpio
中的文件提供了 GPIO 的高级接口。

© www.soinside.com 2019 - 2024. All rights reserved.