汇编LED
Cortex-A汇编:
1、需要用汇编初始化一些SOC外设
2、使用汇编初始化DDR,I.MX6ULL不需要
3、设置sp指针,一般指向DDR,设置好C语言运行环境
ALPHA开发板LED硬件原理分析
ALPHA开发板LED的GPIO为:GPIO1_IO03
STM32 IO初始化流程:
- 使能GPIO时钟
- 设置GPIO复用,将其复用为GPIO
- 配置GPIO的电气属性,如输出功能、上拉、速度等
- 使用GPIO,输出高低电平
I.MX6ULL IO初始化:
-
使能时钟,CCGR0 ~ 6 这7个寄存器,控制6ULL所有外设时钟的使能。简单设置,设置CCGR0 ~ 6 这7个寄存器全部为0XFFFFFFFF(将32位全部设置位1),相当于使能所有外设时钟。
-
IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的bit3 ~ bit0 (MUX_MODE 模式设置)设置为0101(5),这样GPIO1_IO03就复用为GPIO。
-
配置电气属性 寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 用于设置GPIO1_IO03的电气属性。包括压摆率、速度、驱动能力、开漏、上下拉等。
IOMUXC_SW_ MUX _ CTL_PAD_XX_XX
IOMUXC_SW_ PAD _ CTL_PAD_XX_XX
这两种寄存器都用于配置IO,而不是GPIO,GPIO是IO众多复用功能的一种。比如,GPIO1_IO00这个IO可以复用为:I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID、ENET1_REF_CLK、GPIO1_IO00等9个功能。 -
配置GPIO功能,设置输入输出。设置GPIO1_GDIR寄存器的bit3(IO03)为1,即设置为输出模式。设置GPIO1_DR寄存器的bit(IO03),为1表示输出高电平,为0表示输出低电平。
汇编代码如下:
.global _start /* 全局标量 */
/*
* _start,程序从此函数开始执行 此函数完成时钟使能、
* GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
*
*/
_start:
/* 使能所有外设时钟 */
ldr r0, = 0X020C4068 /* CCGR0 */
ldr r1, = 0XFFFFFFFF /* 向CCGR0写入数据 */
str r1, [r0] /* 将0XFFFFFFFF写入到CCGR0中 */
ldr r0, = 0X020C406C /* CCGR1 */
str r1, [r0]
ldr r0, = 0X020C4070 /* CCGR2 */
str r1, [r0]
ldr r0, = 0X020C4074 /* CCGR3 */
str r1, [r0]
ldr r0, = 0X020C4078 /* CCGR4 */
str r1, [r0]
ldr r0, = 0X020C407C /* CCGR5 */
str r1, [r0]
ldr r0, = 0X020C4080 /* CCGR6 */
str r1, [r0]
/* 设置GPIO1_IO03 复用为 GPIO1_IO03 */
ldr r0, = 0X020E0068 /* 寄存器SW_MUX_CTL_PAD_GPIO1_IO03 */
ldr r1, = 0X5 /* 设置寄存器SW_MUX_CTL_PAD_GPIO1_IO03的MUX_MODE为5 */
str r1, [r0]
/* 配置GPIO1_IO03的电气属性
*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_CTL_PAD_GPIO1_IO03 */
ldr r1, = 0X10B0 /* 0X00001000010110000 = 0X10B0 */
str r1, = [r0]
/* 设置GPIO1_IO03为输出 */
ldr r0, = 0X0209C004 /* 寄存器GPIO1_GDIR */
ldr r1, = 0X8 /* 设置寄存器GPIO_GDIR bit3为1 */
str r1, = [r0]
/* 打开LED,即设置GPIO1_IO03为0 */
ldr r0, = 0X0209C000 /* 寄存器GPIO1_DR */
ldr r0, = 0 /* 寄存器值全为0 包括bit3 */
ldr r1, = [r0]
/*
* 描述: loop死循环
*/
loop:
b loop
编译程序
①、使用arm-linux-gnueabihf-gcc,将.c .s文件变为.o
命令: arm-linux-gnueabihf-gcc -g -c led.s -o led.o
②、将所有的.o文件连接为elf格式的可执行文件,链接地址为0x87800000
命令: arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
③、将elf文件转为bin文件。
命令: arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
④、将elf文件转为汇编,反汇编。(可不执行)
命令: arm-linux-gnueabihf-objdump -D led.elf > led.dis
烧录
6ULL支持SD卡、EMMC、NAND、nor、SPI flash等等启动。裸机例程选择烧写到SD卡里面。
在ubuntu下向SD卡烧写裸机bin文件。烧写不是将bin文件拷贝到SD卡中,而是将bin文件烧写到SD卡绝对地址上。而且对于I.MX而言,不能直接烧写bin文件,必须先在bin文件前面添加头部。完成这个工作,需要使用正点原子提供的imxdownload软件。
Imxdownload使用方法,确定要烧写的SD卡文件,我的是/dev/sdb。
给予imxdownload可执行权限:
Chmod 777 imxdownload
烧写:
./imxdownload led.bin /dev/sdb
Imxdownlaod会向led.bin添加一个头部,生成新的load.imx文件,这个load.imx文件就是最终烧写到SD卡里面去的。
相关IO寄存器
GPIO时钟使能
CCGR0 ~ 6 这7个寄存器,控制I.M6ULL所有外设时钟的使能。
CCM_CCGRx是32位寄存器,每2位控制一个外设时钟。例如bit31~30控制着GPIO2的外设时钟。
两个位有四种操作方式:
IOMUXC_SW_MUX_CTL_PAD_XX_XX 详细介绍
寄存器地址为 0X020E005C
这个寄存器是32位的,只用到了最低的5位,其中bit3~bit0(MUX_MODE)就是设置GPIO的复用功能的。
IOMUXC_SW_PAD_CTL_PAD_XX_XX 详细介绍
英文文档:
详细介绍:
GPIO配置
GPIOx_GDIR寄存器
GPIOx_GDIR寄存器是方向寄存器,用于配置GPIO的输入/输出。
32位的GPIOx_GDIR寄存器每一位与每组GPIO的IO对应。如GPIO1_GDIR的bit3对应GPIO1_IO03。如果要设置GPIO为输入模式,就设置相应的位为0,设置为输出模式,就设置相应的位为1。
例如对GPIO1_IO03操作:
输出模式:GPIOx_GDIR(bit3) = 1
输入模式:GPIOx_GDIR(bit3) = 0
GPIOx_DR寄存器
GPIOx_DR寄存器用于存储数据,32位的GPIOx_DR寄存器每一位与每组GPIO的IO对应。如GPIO1_DR的bit3对应GPIO1_IO03。
当GPIO被配置成输出模式后,向DR寄存器写入数据那么相应IO就会输出相应的高低电平;当GPIO被配置成输入模式后,DR寄存器将保存对应IO的电平值。
例如对GPIO1_IO03操作:
高电平:GPIOx_DR(bit3) = 1
低电平:GPIOx_DR(bit3) = 0
GPIOx_PSR寄存器
PSR寄存器是GPIO状态寄存器,同样的PSR寄存器也是一个GPIO对应一个位。读取相应的位即可获取对应GPIO的状态,也就是GPIO的高低电平值。功能和输入状态下的DR寄存器相同。
GPIOx_ICR1 GPIOx_ICR2寄存器
ICR1和ICR2这两个寄存器都是中断控制寄存器,ICR1用于配置低16个GPIO,ICR2用于配置高16个GPIO。ICR1用于IO0 ~ 15的配置,ICR2用于IO16 ~ 31的配置。ICR1寄存器中一个GPIO用两个位,这两个位用来配置中断的触发方式。
如设置GPIO1_IO15为上升沿触发中断,那么GPIO1_ICR = 2 << 30。
GPIOx_IMR 寄存器
IMR寄存器是中断屏蔽寄存器,该32位寄存器也是一个GPIO对应一个位。IMR寄存器用来控制GPIO的中断静止和使能。
如使能某个GPIO的中断,那么设置相应位为1即可,反之,要禁止中断,那么就设置相应的位为0即可。
GPIOx_ISR 寄存器
ISR寄存器是32位寄存器,一个GPIO对应一个位,只要某个GPIO的中断发生,那么ISR寄存器中相应的位会被置1。所以,可以通过读取ISR寄存器判断GPIO中断是否发生,即ISR中这些位就是中断标志位。当处理完中断后,必须清除中断标志位,清除方法就是向ISR中相应的位写1,也就是 写1清零。
GPIOx_EDGE_SET 寄存器
EDGE_SET寄存器是边沿选择寄存器,用来设置边沿中断,一个GPIO对应一个位。EDGE_SET寄存器会覆盖ICR1和ICR2的设置。如果相应的位被置1,那就相当于设置对应的GPIO是上升沿和下降沿(双边沿)触发。