我开始使用树莓派 pico 学习汇编语言和 ARM。
我什至一直在关注《RP2040汇编语言编程》这本书,但是没有关于如何仅使用汇编读取输入引脚的说明。 这是我的设置:我有一个按钮,未按下时发送 3.3V,按下时发送 0V。
我希望能够使用 GPIO 引脚读取不同的状态,但尽管查看了数据表的功能(我几乎不明白,因为这是我第一次处理它),我不知道如果我所做的事情有意义的话。
这是我的代码:
led_loop:
@ set the control for the push
ldr r0, =ctrl2 @ control register for GPIO1 0x40014008
mov r1, #5 @ Function 5, select SIO for GPIO1 2.19.2
str r1, [r0] @ Store function_5 in GPIO1 control register
@ shifts over "1" the number of bits of GPIO pin
mov r2, #1 @ load a 1 into register 1
lsl r2, r2, #1 @ move the bit over to align with GPIO1
ldr r0, =sio_base @ SIO base 0xd0000000
str r1, [r0, #0x00000004] @ 0x004 GPIO input enable
ldr r0, =helloworld
BL printf
b led_loop @ do the loop again
.data
.align 4
helloworld: .asciz "Hello World %d\n"
到目前为止,我尝试查阅数据表,但我没有足够的知识来识别我所做的是否是写的或错误的。
这是 C,使用原始 picos 上的 LED,不确定是否再是这种情况。
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void DELAY ( unsigned int );
#define RESETS_BASE 0x4000C000
#define RESETS_RESET_RW (RESETS_BASE+0x0+0x0000)
#define RESETS_RESET_XOR (RESETS_BASE+0x0+0x1000)
#define RESETS_RESET_SET (RESETS_BASE+0x0+0x2000)
#define RESETS_RESET_CLR (RESETS_BASE+0x0+0x3000)
#define RESETS_RESET_DONE_RW (RESETS_BASE+0x8+0x0000)
#define RESETS_RESET_DONE_XOR (RESETS_BASE+0x8+0x1000)
#define RESETS_RESET_DONE_SET (RESETS_BASE+0x8+0x2000)
#define RESETS_RESET_DONE_CLR (RESETS_BASE+0x8+0x3000)
#define SIO_BASE 0xD0000000
#define SIO_GPIO_IN (SIO_BASE+0x04)
#define SIO_GPIO_OUT_RW (SIO_BASE+0x10)
#define SIO_GPIO_OUT_SET (SIO_BASE+0x14)
#define SIO_GPIO_OUT_CLR (SIO_BASE+0x18)
#define SIO_GPIO_OUT_XOR (SIO_BASE+0x1C)
#define SIO_GPIO_OE_RW (SIO_BASE+0x20)
#define SIO_GPIO_OE_SET (SIO_BASE+0x24)
#define SIO_GPIO_OE_CLR (SIO_BASE+0x28)
#define SIO_GPIO_OE_XOR (SIO_BASE+0x2C)
#define IO_BANK0_BASE 0x40014000
#define IO_BANK0_GPIO25_CTRL_RW (IO_BANK0_BASE+0x0CC+0x0000)
#define IO_BANK0_GPIO25_CTRL_XOR (IO_BANK0_BASE+0x0CC+0x1000)
#define IO_BANK0_GPIO25_CTRL_SET (IO_BANK0_BASE+0x0CC+0x2000)
#define IO_BANK0_GPIO25_CTRL_CLR (IO_BANK0_BASE+0x0CC+0x3000)
#define IO_BANK0_GPIO1_CTRL_RW (IO_BANK0_BASE+0x00C+0x0000)
#define IO_BANK0_GPIO1_CTRL_XOR (IO_BANK0_BASE+0x00C+0x1000)
#define IO_BANK0_GPIO1_CTRL_SET (IO_BANK0_BASE+0x00C+0x2000)
#define IO_BANK0_GPIO1_CTRL_CLR (IO_BANK0_BASE+0x00C+0x3000)
int notmain ( void )
{
unsigned int ra;
PUT32(RESETS_RESET_CLR,1<<5); //IO_BANK0
while(1)
{
if((GET32(RESETS_RESET_DONE_RW)&(1<<5))!=0) break;
}
PUT32(SIO_GPIO_OE_CLR,1<<25);
PUT32(SIO_GPIO_OUT_CLR,1<<25);
PUT32(IO_BANK0_GPIO25_CTRL_RW,5); //SIO
PUT32(SIO_GPIO_OE_SET,1<<25);
for(ra=0;ra<10;ra++)
{
PUT32(SIO_GPIO_OUT_XOR,1<<25);
DELAY(0x40000);
}
PUT32(SIO_GPIO_OE_CLR,1<<1);
PUT32(SIO_GPIO_OUT_CLR,1<<1);
PUT32(IO_BANK0_GPIO1_CTRL_RW,5); //SIO
while(1)
{
ra=GET32(SIO_GPIO_IN);
if(ra&2)
{
PUT32(SIO_GPIO_OUT_SET,1<<25);
}
else
{
PUT32(SIO_GPIO_OUT_CLR,1<<25);
}
}
return(0);
}
严格从文档中查找所有这些地址和信息是,嗯......
PUT32 只是一个存储字,GET32 只是一个加载字。延迟只是一个计数到零的循环。
GPIO通常默认/重置为输入,清除out/oe并使其成为我可能直接从他们的库中获得的输入,这是必需的吗?不知道,也许可以读取那些寄存器并看到。
您确实需要释放 I/O 块上的复位,所以也许您在其他地方这样做。
上面的 LED 闪烁 5 次,然后进入轮询循环,读取 GPIO 并隔离 GPIO 1(如果为高电平),然后点亮 LED(如果为低电平,则不点亮 LED)。
将其转换为 asm 很简单,应该能够看到你所做的和我所做的差异,并决定是否需要清除 out/oe 设置。您的地址错误,正在写入您应该读取的内容,并且 IO 块至少无法重置。