裸机点亮LED灯
该实验使用正点原子的linux开发板和下载工具
知识储备
GPIO时钟控制器
在《IMX6ULL用户手册》中,时钟控制器模块介绍在第18章
首先看CCM Clock Gating Register 0 (CCM_CCGR0) ~ CCM Clock Gating Register 6 (CCM_CCGR6) ,这7个寄存器是用来控制每个模块的时钟。这些寄存器都是32位的,每两个位控制一个外设的时钟。如下是配置效果:
- 00:所有模式下都关闭外设时钟。
- 01:只有在运行模式下打开外设时钟,等待模式和停止模式下均关闭外设时钟。
- 10:reserve。
- 11:除了停止模式以外,其他所有模式下时钟都打开。
如图是CCM_CCGR0时钟配置寄存器,寄存器地址为 0x02C4068,另外6个寄存器和这个基本一致,只是控制的外设不同。
IO口复用控制器
位于《IMX6ULL参考手册》的第32章节,章节目录如下所示:
IO口分为两类:SNVS域(Secure Non-Volatile Storage 安全的非易失性存储)对应的IO和常用的IO
以IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03为例:
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的复用功能配置寄存器
绿色方框中则是这个寄存器的地址。向该寄存器地址对应的内存空间写入数据即配置这个寄存器的功能。
可以看出,这个IO可以复用为8种不同功能的IO,并且由MUX_MODE来决定,那么配置服用模式的时候实际上就是对该IO口的复用功能配置寄存器的MUX_MODE段写入对应的值。而SION段则是配置是否使能读电平的功能,即如果使能,那么在IO口为输出模式的情况下依然能够读取当前IO的电平。
IO口属性配置寄存器
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的属性配置寄存器
该寄存器只使用了低17位。
(HYS)bit 16:配置是否使能HYS
(PUS)bit [15:14]: 00 配置下拉(100k下拉电阻),01配置上拉(47k上拉电阻),10配置上拉(100k上拉电阻),11配置上拉(22k上拉)
(PUE)bit [13]:配置状态保持功能,该功能只在IO作为输入时才有用。0:使用状态保持器,1:使用上下拉
(PKE)bit [12]:0:禁止上下拉/状态保持器,1:使能上下拉/状态保持器
(ODE) bit [11]:0:关闭开路输出,1:开启开路输出
(SPEED)bit [7:6]:配置IO速度。00:低速50M,01:中速100M,10:中速100Mhz,11最大速度200M
(DSE)bit [5:3]:配置IO口用作输出的时候,IO口的驱动能力
(SRE)bit [0]:配置电平跳变的转换率,即IO口电平跳变需要的时间。0:低转换率,1:高转换率
GPIO相关寄存器
当引脚作为GPIO口的时候要配置的寄存器的概述图如下,在参考手册的第28章:通用输入/输出,1343页。
IOMUXC中有SW_MUX_CTL_PAD 和 SW_MUX_CTL_PAD,分别就是前面的配置IO口复用和属性的寄存器。
GPIO框图中有8个寄存器,分别是:
- Data register (GPIO_DR):数据寄存器(32位),一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应一个 GPIO。
- GPIO direction register (GPIO_GDIR):方向寄存器(32位),即配置输入输出。0:输入,1:输出。
- Pad sample register (GPIO_PSR):状态寄存器(32位),用于获取GPIO的高低电平值。
- Interrupt control registers (GPIO_ICR1, GPIO_ICR2):中断控制寄存器,ICR1配置低16个GPIO,ICR2配置高16位个GPIO。
两个位对应四种触发状态:00:低电平触发,01:高电平触发,10:上升沿触发,11:下降沿触发。 - Edge select register (GPIO_EDGE_SEL):配置边沿中断寄存器(32位):配置该寄存器会覆盖 ICR1 和 ICR2 的设置,置1则为双边沿触发。
- Interrupt mask register (GPIO_IMR):中断屏蔽寄存器(32位),用于使能或禁止中断。
- Interrupt status register (GPIO_ISR):中断标志位寄存器(32位),只要某个 GPIO 的中断发生,那么 ISR 中相应的位就会被置 1。通过读取这个寄存器的值可以判断中断是否产生,但是要记得在处理完中断后,要手动清除中断标志位,即向ISR中对应位写1。
点灯步骤
①、使能 GPIO 对应的时钟。(配置GPIO时钟控制器)
②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能。(配置IO口复用控制器)
③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等属性。(配置IO口属性控制器)
④、第②步已经将 IO 复用为了 GPIO 功能,所以需要配置 GPIO,设置输入/输出、是否使用中断、默认输出电平等。(配置GPIO相关属性控制器)
接下来以点亮GPIO1_IO03的LED灯为例:
①、使能GPIO1对应的外设时钟,外设时钟为CCM_CCGR1,寄存器地址为0x20C406C,写入0x0C0C0000;在参考手册700页。
(这里有个疑问,本来我认为将CG13即 gpio1 clock 配置为1即可;但是在测试过后,发现CG9也要使能,CG9对应的是sim_s clock。目前还不知道这干啥用的,为啥这个也要置1。)
②、配置复用功能,GPIO1_IO03的复用功能配置寄存器地址为0x020E0068,在参考手册1571页,配置为ALT5模式,如图:
即给寄存器写入0x5就行。
③、配置IO口的属性,可直接按下图红框里配置,即向**IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器(地址:0x020E02F4)**写入 0x10B0。在参考手册1793页
④、配置GPIO的其它属性:输入/输出、是否使用中断、默认输出电平等。(内容位于参考手册1357~1359页)
-
先配置GPIO方向为输出方向,即向GPIO1_GDIR寄存器的GPIO3的位置写入1。地址为0x0209_C004。
-
再向对应的数据寄存器写入数据,地址为0x0209C000,写0表示低电平
配置完后,烧入SD卡,就可以点亮LED灯了。
最后附上汇编代码
.global _start /* 全局标号 */
/*
* 描述: _start函数,程序从此函数开始执行此函数完成时钟使能、
* GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
*/
_start:
/* 1、使能时钟 */
ldr r0, =0X020C406C /* CCGR1 */
ldr r1, =0x0c0c0000
str r1, [r0]
/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
ldr r0, =0X020E0068 /* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
ldr r1, =0X5 /* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
str r1,[r0]
/*
*3、配置GPIO1_IO03的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
*/
ldr r0, =0X020E02F4 /*寄存器SW_PAD_GPIO1_IO03_BASE */
ldr r1, =0X10B0
str r1,[r0]
/* 4、设置GPIO1_IO03为输出 */
ldr r0, =0X0209C004 /*寄存器GPIO1_GDIR */
ldr r1, =0X0000008
str r1,[r0]
/* 5、打开LED0
* 设置GPIO1_IO03输出低电平
*/
ldr r0, =0X0209C000 /*寄存器GPIO1_DR */
ldr r1, =0
str r1,[r0]
/*
* 描述: loop死循环
*/
loop:
b loop