我正在尝试使用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
并且它给出了分段错误,有人可以帮我解决这个问题吗
该程序被编写为无需操作系统即可直接访问物理地址空间,但您在配置虚拟内存的 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 的高级接口。