第六章 Contex-A7 MPCore架构
Contex-A处理器运行模型
以前的ARM处理器有七种运行模式,现在有九种,新增加Monitor和Hyp运行模式。
模式 | 描述 |
---|---|
USR(User) | 用户模式,非特权模式,大部分程序运行的时候处于此模式 |
FIQ | 快速中断模式,进入FIQ中断异常 |
IRQ | 一般中断模式 |
SVC(Supervisor) | 超级管理员模式,特权模式,宫操作系统使用 |
MON(Monitor) | 监视模式,这个模式用于安全扩展模式,指用户安全 |
ABT(Abort) | 数据访问终止模式,用于虚拟存储以及存储保护 |
HYP(Hyp) | 超级监视模式,用于虚拟化扩展 |
UND(Undef) | 未定义指令终止模式 |
SYS(System) | 系统模式,用于运行特权级的操作系统任务 |
记忆(UFIS MAHUS)
Contex-A寄存器组
ARM提供了16个32位通用寄存器(R0R15)供软件使用,前15个(R0R14)可以用作通用的数据存储,R15是程序计数器PC,用来保存将要执行的命令,ARM还提供了一个当前程序状态寄存器CPSR和一个备份程序寄存器SPSR,SPSR是CPSR的备份。
总结一下, Cortex-A内核寄存器组成如下(共43个):
①、 34个通用寄存器,包括 R15程序计数器 (PC),这些寄存器都是 32位的。
②、 8个状态寄存器,包括 CPSR和 SPSR。
③、 Hyp模式下独有一个 ELR_Hyp寄存器。
第七章 ARM汇编基础
学习汇编的目的:初始化C语言运行环境。
GNU汇编语法
label:instruction@comment
label:标号,表示地址位置,有些指令前面可能会有标号
instruction:指令,即汇编指令或者伪指令
@:注释符号
comment:注释内容
示例代码:
add:
MOVS R0, #0X12 @设置 R0=0X12
注意! ARM中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用
小写,但是不能大小写混用。
用户可以使用.section伪操作来定义一个段,汇编系统预定义了一些段名:
.text 表示代码段
.data 表示初始化的数据段
.base 表示未初始化的数据段
.rodata 表示只读数据段
Contex-A7常用的汇编指令
处理器做的最多的事情就是在处理器内部来回传递数据,常见的操作有:
- 将数据从一个寄存器传递到另一个寄存器。
- 将数据从一个寄存器传递到特殊寄存器,如CPSR和SPSR.
- 将立即数传递到寄存器。
数据传输常用的指令有三个:MOV、MRS、MSR.
处理器内部传输指令
指令 | 目的 | 源 | 描述 |
---|---|---|---|
MOV | R0 | RI | 将R1里面的数据复制到R0中 |
MRS | R0 | CPSR | 将特殊寄存器CPSR里面的数据复制到R0 |
MSR | CPSR | RI | 将R1里面的数据复制到特殊寄存器CPSR里 |
存储器访问指令
指令 | 描述 |
---|---|
LDR Rd, [Rn , #offset] | 从存储器Rn+offset的位置读取数据存放到 Rd中 |
STR Rd, [Rn, #offset] | 将Rd中的数据写入到存储器中的 Rn+offset位置。 |
压栈和出栈指令
指令 | 描述 |
---|---|
PUSH | 将寄存器列表入栈 |
POP | 从栈中恢复寄存器列表 |
PUSH 和POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”。
跳转指令
有多种跳转指令
- 直接使用调转指令B、BL、BX等。
- 直接向PC寄存器里面写入数据。
指令 | 描述 |
---|---|
B | 调转到label,如果跳转范围超过+/-2KB,可以指定B.W |
BX | 间接跳转,跳转到存放Rm中的地址处,并且切换指令集 |
Bl | 跳转到标号地址,并将返回地址保存在LR中 |
BlX | 结合BX和BL的特点,跳转到Rm指定的地址,并将返回地址保存在LR中,切换指令集 |
第八章 汇编LED灯实验
IO控制初始化所需要用到的寄存器
1. SW_MUX_CTL Register
Address:20E_0000h base+5Ch offset=20E_005Ch
2. SW_PAD_CTL Register
Address:20E_0000h base+2E8h offset=20E_02E8h
从上图中可以看出,该寄存器只用到了低17位:
HYS(Bits16):用来使能迟滞比较器,输入有效时,需要对输入波形进行整形可以使用此使能位,0禁止,1使能。
PUS(Bits15:14):用来设置上下拉电阻,
位设置 | 含义 |
---|---|
00 | 100K下拉 |
01 | 47K上拉 |
10 | 100K上拉 |
11 | 22K上拉 |
PUE(Bits13):用来设置IO使用上下拉还是状态保持器,0为状态保持器,1为使用上下拉,状态保持器在IO作为输入时才有效。
PKE(Bits12):用来使能或者禁止上下拉/状态保持器功能,为0禁止上下拉/状态保持器,为1使能上下拉和状态保持器。
SPEED(Bits7:6):当IO用作输出时,设置IO速度。
位设置 | 速度 |
---|---|
00 | 低速50M |
01 | 中速100M |
10 | 中速100M |
11 | 最大速度200M |
DSE(Bits5:3):用来设置IO的驱动能力。
位设置 | 速度 |
---|---|
000 | 输出驱动关闭 |
001 | R0(3.3V下 R0是 260Ω, 1.8V下 R0是 150Ω,接 DDR的时候是 240ΩΩ) |
010 | R0/2 |
011 | R0/3 |
100 | R0/4 |
101 | R0/5 |
110 | R0/6 |
111 | R0/7 |
DSE(Bits5:3):设置压摆率,压摆率指的是IO电平跳变所需要的时间,时间越短压摆率越高,反之越低。过EMC需要低压摆率,高速通信需要高压摆率。
3.GPIO的配置
IOMUXC_SW_MUX_CTL_PAD_XX_XX和 IOMUXC_SW_PAD_CTL_PAD_XX_XX这两种寄存器都是配置 IO的,注意以下IO与GPIO的区别,GPIO是IO众多复用的其中一种。
当IO用作GPIO时需要设置的寄存器共有8个:DR、GDIR、PSR、ICRC、ICR2、EDGE_SEL、IMR和ISR…
DR寄存器
一个GPIO组最大只有32个IO,DR寄存器的每一个位对应一个GPIO,当GPIO被设置成输出功能后,相应的IO就会输出相应的高低电平,置1为高电平,置0为低电平。当GPIO被设置成输入功能后,该寄存器将会保存对应IO的电平值,1为高电平,0为低电平。
GDIR寄存器
GDIR也是32位,用来设置某个IO的工作方向,是输入还是输出,一个IO对应一个位,置0为输入,置1为输出。
PSR寄存器
PSR是GPIO状态寄存器,一个GPIO对应一个位,读取相应的位即可获取GPIO的状态,也就是GPIO的高低电平。功能和输入状态下的DR寄存器一样。
ICR1和ICR2寄存器
ICR1和ICR2是中断控制寄存器,ICR1用于配置低16位GPIO,ICR2用于配置高16位。配置选线如下表:
位设置 | 速度 |
---|---|
00 | 低电平触发 |
01 | 高电平触发 |
10 | 上升沿触发 |
11 | 下降沿触发 |
IMR寄存器
IMR寄存器是中断屏蔽寄存器,也是一个GPIO对应一个位,使能GPIO中断置1,反之禁止。
ISR寄存器
ISR寄存器是中断状态存器,也是一个GPIO对应一个位,某个GPIO中断发生了,相应的位将会被置1,我们可以通过读取ISR来判断GPIO是否发生中断,当中断处理完成之后,必须清除中断标志位,清除方法是向ISR相应的位写1,也就是清零。
EDGE_SEL寄存器
EDGE_SEL寄存器用来设置边沿中断,这个寄存器会覆盖ICR1和ICR2的设置,同样是一个GPIO对应一个位,置1表示双边沿触发中断,无论GPIO_CR1设置的是多少,都是双边沿触发。
### 时钟使能 I.MX6U的系统时钟参考 《 I.MX6UL参考手册》的第 18章“ Chapter 18: Clock Controller Module(CCM)”,这一个章主要将时钟系统。目前不研究,只看CMM的外设时钟使能寄存器。CMM有CCM_CCGR0~CCM_CCGR6这7个寄存器, ##### CCM_CCGR0 寄存器 
CCM_CCGR0是32位寄存器,其中每2位控制一个外设时钟,比如bit31:30控制着GPIO2的外设时钟,两个位有4种操作方式。
位设置 | 时钟控制 |
---|---|
00 | 所有模式下都关闭外设时钟 |
01 | 只有在运行模式下打开外设时钟,等待模式和停止模式均关闭外设时钟 |
10 | 未使用(保留) |
11 | 除了停止模式以外,其他所有模式下时钟都打开 |
I.MX6U的IO作为GPIO使用,初始化步骤如下:
1. 使能GPIO对应时钟。
2. 设置寄存器IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置IO复用功能,使其复用位GPIO功能。
3. 设置寄存器IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置IO的上下拉、速度等等。
4. 第2步已经将IO复用为GPIO功能,所以需要配置GPIO,设置输入/输出、是否使能中断、默认输出电平等。
示例代码:
.global _start
_start:
/*
*1.使能所有的时钟(CCGR0~CCGR1)
*/
ldr r0,=0x020C4068 /*打开CCM_CCGR0寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C406C /*打开CCM_CCGR1寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C4070 /*打开CCM_CCGR2寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C4074 /*打开CCM_CCGR3寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C4078 /*打开CCM_CCGR4寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C407C /*打开CCM_CCGR5寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
ldr r0,=0x020C4080 /*打开CCM_CCGR6寄存器的所有时钟*/
ldr r1,=0xFFFFFFFF
str r1,[r0]
/*
*2.设置复用
*/
ldr r0,=0x02E00068
ldr r1,=0x00000005
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
*低转换率 48
*/
ldr r0,=0x020E02F4
ldr r1,=0x000010B0
ldr r1,[r0]
/*
*4.设置GPIO1_IO3为输出
*/
ldr r0,=0x0209C004 /*配置GDIR寄存器*/
ldr r1,=0x00000008 /*默认电平为1*/
str r1,[r0]
/*
*5.打开LED0,设置GPIO1_IO03为高电平
*/
ldr r0,=0x0209C0000 /*配置DR寄存器*/
ldr r1,=0x000000000 /*默认电平为1*/
str r1,[r0]
/*
*loop死循环
*/
loop:
b loop
Makefile文件编写
led.bin:led.s
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-guneabihf-objdump -D led.elf > led.dis
clean:
rm -rf *.o led.bin led.elf led.dis
arm-linux-gnueabihf-gcc -g -c led.s -o led.o(编译文件)
arm-linux-gnueabihf-gcc :表示编译文件;
-g:选项表示产生调试信息;
-c:选项表示编译源文件,但是不链接;
-o:选项表示指定编译产生的文件名字。
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf(链接文件)
arm-linux-gnueabihf-ld:表示将众多的.o文件链接到一个指定的链接位置;
-Ttext:表示连接时将初始地址重定向为0x87800000;
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin(格式转换)
arm-linux-gnueabihf-objcopy 表示将led.elf文件转换成led.bin文件;
-O:选项表示指定以什么格式输出;
binary:表示以二进制格式输出;
-S:表示不要复制源文件的重定位信息和符号信息;
-g:表示不要复制源文件中的调试信息。
arm-linux-guneabihf-objdump -D (-m arm)led.elf > led.dis(反汇编)
arm-linux-gnueabihf-objdump:表示进行反汇编,用来查看其汇编代码来调试代码;
-D:表示反汇编所有的段;
-m:表示后面跟CPU架构;
>:表示将这个程序的反汇编程序写入到led.dis这个文件中,在终端中不显示出来。
第九章 I.MX6U的启动方式
启动方式选择
BOOT模式有两种
1.改写eFUSE(熔丝);
2. 修改相应的GPIO高低电平。
第一种修改eFUSE的方式只能修改一次,后面就不能再修改了,所以作为学习与调试我们不能使用。第二种是修改GPIO对应的高低电平来选择启动方式,所有的开发板都使用这种方式。
BOTE_MODE[1:0] | BOOT类型 |
---|---|
00 | 从FUSE启动 |
01 | 串行下载 |
10 | 内部BOOT模式 |
11 | 保留 |
开发板只用到第二和第三种BOOT方式。
串行下载
串行下载是指可以通过USB或UART将代码下载到外置存储设备中,所以我们可以使用OTG1这个USB口向开发板的存储设备下载代码。使用时需要用到NXP提供的一个软件,一般用来最终量产的时候烧写到外置存储设备中。
内部BOOT模式
在此模式下,芯片会执行内部boot ROM代码,这段boot ROM代码会进行硬件初始化,然后从boot设备(存储代码的设备如SD/EMMC/NAND)将代码拷贝至指定的RAM,一般是DDR。
BOOT ROM初始化内容
BOOT 启动设备
除了BOOT_MODE1和BOOT_MODE0必须引出来,LCD_DATA3LCDDATA7、LCD_DTAT11这六个IO也被引出来,可以通过拨码开关进行设置,其中LCD_DTAT11是BOOT_CFG2[3],LCD_DAT3LCD_DATA7就是BOOT_CFG[3]~BOOT_CFG1[7],这六个IO配置如下:
BOOT_CFG引脚[1:0] | 对应LCD引脚 | 含义 |
---|---|---|
BOOT_CFG2[3] | LCD_DATA11 | LCD_DATA11|为0时从SDHC上的SD/EMMC启动,为1时从SDHC2上的SD/EMMC启动 |
BOOT_CFG1[3] | LCD_DATA3 | 当从SD/EMMC启动的时候设置启动速度,当从NAND启动的话设置NAND数量 |
BOOT_CFG1[4] | LCD_DATA4 |
BOOT_CFG1[7:4] 0000 NOR/OneNAND(EIM)启动。 0001 QSPI 启动。 0011 SPI启动。 010x SD/eSD/SDXC启动。 011x MMC/eMMC启动。 1xxx NAND Flash启动。 |
BOOT_CFG1[5] | LCD_DATA5 | |
BOOT_CFG1[6] | LCD_DATA6 | |
BOOT_CFG1[7] | LCD_DATA7 |
来源:CSDN
作者:岁月静好莫视流年
链接:https://blog.csdn.net/qq_25935169/article/details/103244473