Raspberry PI 系列 —— 裸机点亮LED灯
Raspberry PI 系列 —— 裸机点亮LED灯
背景
最近刚买了Raspberry PI B+,配置运行了官方提供的Raspbian系统,折腾了一周Linux系统,感觉没啥意思,于是就试着想了解底层的启动流程,通过几天的研究,发现最底层部分的启动是由官方提供的bootcore.bin和start.elf文件来执行(应该是对硬件设备的初始化,如MMU等),之后由下一部分kernel.img的_start接管。为了真正验证此流程,于是想利用GPIO控制LED灯,几经折腾终于成功点亮LED,现记录于此。
外设地址编码
要想控制GPIO管脚就必须知道GPIO管脚的地址,在ARM架构中外设IO一般采用统一编码,BCM2835将外设地址0x7E00000映射到RAM的0x20000000,如0x7E200000则为0x20200000,下面是总线地址、物理地址、虚拟地址关系图:
GPIO扩展口
本次我们要通过板子上预留的GPIO管脚来控制LED灯,这里必须了解这些管脚的含义,B+版本的GPIO口扩展到了40脚,下图是B与B+的GPIO管脚区别:
GPIO寄存器
在BCM2835中,共有54个GPIO管脚,其中GPIO寄存器有GPFSELn、GPSETn、GPCLRn等,下面具体描述这些寄存器的作用:
· 寄存器 GPFSEL0 ~ GPFSEL5 ---- 功能寄存器,指定管脚为输入、输出等, 每3位决定一个管脚:
o 000 = GPIO Pin 9 is aninput
o 001 = GPIO Pin 9 is anoutput
o 100 = GPIO Pin 9 takesalternate function 0
o 101 = GPIO Pin 9 takesalternate function 1
o 110 = GPIO Pin 9 takesalternate function 2
o 111 = GPIO Pin 9 takesalternate function 3
o 011 = GPIO Pin 9 takesalternate function 4
o 010 = GPIO Pin 9 takesalternate function 5
其中:(寄存器---地址---描述)
* GPFSEL0 --- 0x7E200000 --- 决定GPIO0-GPIO9管脚的功能
* GPFSEL1 --- 0x7E200004 --- 决定GPIO10-GPIO19管脚的功能
* GPFSEL2 --- 0x7E200008 --- 决定GPIO20-GPIO29管脚的功能
* GPFSEL3 --- 0x7E20000c --- 决定GPIO30-GPIO39管脚的功能
* GPFSEL4 --- 0x7E200010 --- 决定GPIO40-GPIO49管脚的功能
* GPFSEL5 --- 0x7E200014 --- 决定GPIO50-GPIO53管脚的功能
· 寄存器 GPSET0 - CPSET1 ---- 设为1, 每一位决定一个管脚
o 0 = No effect
o 1 = Set GPIO pin n
其中:(寄存器---地址---描述)
* GPSET0 --- 0x7E20001C --- 决定GPIO0-GPIO31管脚
* GPSET1 --- 0x7E200020 --- 决定GPIO32-GPIO53管脚
· 寄存器 GPCLR0 - GPCLR1 ---- 设为0, 每一位决定一个管脚
o 0 = No effect
o 1 = Clear GPIO pin n
其中:(寄存器---地址---描述)
* GPSET0 --- 0x7E200028 --- 决定GPIO0-GPIO31管脚
* GPSET1 --- 0x7E20002C --- 决定GPIO32-GPIO53管脚
例子 --- 设置GPIO16为低电平
不多说了,该介绍的,前面已经介绍过了,直接上代码:
.section .init
.globl _start
_start:
ldr r0,=0x20200000
/* Set GPIO16 to output mode(001) */
mov r1,#1
lsl r1,#18
str r1,[r0,#4] /* GPFSEL1(决定GPOI10 - GPIO19) */
/* Clear GPIO16 */
mov r1,#1
lsl r1,#16
str r1,[r0,#40] /* GPCLR0(决定GPOI0 - GPIO31) */
/*
* Loop over this forevermore
*/
loop$:
b loop$
结果:
总结
经过了多次的尝试终于点亮了LED灯,虽然现在想起,可能非常简单,当这毕竟是零的突破,在这一小步中,掌握了很多知识,如总线地址、物理地址的关系,如何看GPIO寄存器,ARM的汇编指令等等,有了这一步的成功我就能进行更多复杂的实验。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。