目录
- 前言
- 一、Ubuntu及linux系统基础知识
- 1.shell命令的运用
- 2.Tool的安装:
- 3.deb是软件包,dpkg是手动安装工具,apt是自动安装工具,
- 4.Linux文件系统
- 5.gcc编译器
- 二、开发环境搭建
- 1.vim编辑器
- 2.与windows文件互传
- 3.VSCode使用
- 4.NFS网络文件系统(可以让开发板与主机互传文件)
- 5.交叉编译器安装(有时候存在没用的情况换4.9版本)
- 6.Windows下终端登录(MobaXterm或者Xshell)
- 三、ARM启动及开发基础
- 1.Cortex-A架构
- 2.启动方式
- 3.汇编基础
- 4.Makefile语法基础
- 5.编译下载
- 四、裸机开发
- 1.GPIO详解
- 2.中断
- 3.时钟
- 4.UART串口通信
- 5.Makefile补充
- 结语
前言
主要介绍linux开发的基础,如Ubuntu的使用、环境搭建,及ARM裸机开发及基础知识
一、Ubuntu及linux系统基础知识
1.shell命令的运用
1)查看文件路径:pwd
2)打开新终端:ctrl+alt+T
3)补全命令或者文件:tab键
2.Tool的安装:
虚拟机-安装VMware Tool-在桌面生成一个DAD光盘-将tar.gz格式压缩包复制到home文件夹里-提取到此处-运行install.pl
1)sudo ./vmware-install.pl
2)输入密码-回车-输入路径-安装完成-重新启动-提示选择否
3.deb是软件包,dpkg是手动安装工具,apt是自动安装工具,
1)deb包的组成结构
①控制信息(放在DEBIAN目录下),本deb包的DEBIAN目录下有changelog、 control、copyright、postinst等文件。changelog 文件记录了该deb 包的作者、版本以及最后一次更新日期等信息;control 文件记录了包名、版本号、架构、维护者及描述等信息;copyright 文件记录了一些版权信息;postinst 记录了在安装deb 包后的欢迎词信息。
②安装的内容,这部分类似linux 的根目录,如根目录下的/home/debian/peripheral 存放着我们的运行脚本。
(1)control:deb 包必要的文件,它描述了软件包的名称、版本号、描述信息、所支持的处理器架构等,它可供deb 包安装管理及索引。
(2)postinst:包含了软件在进行正常目录文件拷贝到系统后,所需要执行的配置工作。
(3)postrm 文件:软件卸载后需要执行的脚本。
2)apt包含了apt-get(安装与更新)、apt-cache(查询软件包的相关信息)和apt-config(配置apt工具),命令如下:
sudo dpkg -i xxxx.deb #解压
sudo apt-get install 软件名 #安装软件包 sudo
apt-get remove 软件包名 #卸载
4.Linux文件系统
| 文件名 | 文件类型 |
|---|---|
| /bin | 存储一些二进制可执行命令文件,/usr/bin 也存放了一些基于用户的命令文件。 |
| /sbin | 存储了很多系统命令,/usr/sbin 也存储了许多系统命令。 |
| /root | 超级用户 root 的根目录文件。 |
| /home | 普通用户默认目录,在该目录下每个用户都有一个以本用户名命名的文件夹 |
| /boot | 存放 Ubuntu 系统内核和系统启动文件。 |
| /mnt | 通常包括系统引导后被挂载的文件系统的挂载点 |
| /dev | 存放设备文件,我们后面学习 Linux 驱动主要是跟这个文件夹打交道的。 |
| /etc | 保存系统管理所需的配置文件和目录。 |
| /lib | 保存系统程序运行所需的库文件,/usr/lib 下存放了一些用于普通用户的库文件。 |
| /lost+found | 一般为空,当系统非正常关机以后,此文件夹会保存一些零散文件。 |
| /var | 存储一些不断变化的文件,比如日志文件 |
| /usr | 包括与系统用户直接有关的文件和目录,比如应用程序和所需的库文件。 |
| /media | 存放Ubuntu系统自动挂载的设备文件。 |
| /proc | 虚拟目录,不实际存储在磁盘上,通常用来保存系统信息和进程信息。 |
| /tmp | 存储系统和用户的临时文件,该文件夹对所有的用户都提供读写权限。 |
| /opt | 可选文件和程序的存放目录。 |
| /sys | 系统设备和文件层次结构,并向用户程序提供详细的内核数据信息。 |
5.gcc编译器
1)相关命令
①gcc -v:查看版本号
②which gcc:查看安装路径
2)组成部分
①gcc-core:即GCC 编译器,用于完成预处理和编译过程,例如把C 代码转换成汇编代码。
②Binutils 工具集:as(汇编器)、ld(链接器)、readelf(查看信息)等位于/usr/bin目录
③glibc 库是GNU 组织为GNU 系统以及Linux 系统编写的C 语言标准库
3)编译命令
编译过程:hello.c(预处理-E)→hello.i(编译-S)→hello.s(汇编-c)→hello.o(链接)->hello(可执行文件)
gcc hello.c -o hello #使用gcc把hello.c编译称hello
gcc hello.c -o hello --static #静态编译,没有库也能运行
二、开发环境搭建
1.vim编辑器
sudo apt install vim #安装vim
sudo vi /etc/vim/vimrc #对vim的配置如下:
set ts=4:设置TAB为4个空格
set nu:设置显示行号
set noexpandtab:禁止用空格代替TAB键
2.与windows文件互传
①sudo apt-get install vsftpd:安装FTP服务
②sudo vi /etc/vsftpd.conf:配置FTP
local_enable=YES
write_enable=YES
③sudo /etc/init.d/vsftpd restart:重启FTP服务
④安装FileZilla->站点管理器设置连接
3.VSCode使用
1)sudo dpkg -i 安装包的名字
2)sudo code 文件名 –user-data-dir:使用VS Code修改配置文件
3)插件安装
(1)C/C++,这个肯定是必须的。
(2)C/C++ Snippets,即C/C++重用代码块。
(3)C/C++ Advanced Lint,即C/C++静态检测。
(4)Code Runner,即代码运行。
(5)Include AutoComplete,即自动头文件包含。
(6)Rainbow Brackets,彩虹花括号,有助于阅读代码。
(7)GBKtoUTF8,将GBK转换为UTF8。
(8)ARM,即支持ARM汇编语法高亮显示。
(9)Chinese(Simplified),即中文环境。
(10)vscode-icons,VSCode图标插件,主要是资源管理器下各个文件夹的图标。
(11)DeviceTree,设备树语法插件。
(12)TabNine,一款AI自动补全插件,强烈推荐,谁用谁知道!
4)VScode的设置
①设置里搜索预览→取消选中Enable Preview
5)创建.vscode文件夹
①c_cpp_properties.json的配置文件
(1)includePath:用于指定工程头文件路径
②新建一个名为“settings.json”
(1)其中"search.exclude"里面是需要在搜索结果中排除的文件或者文件夹
(2)"files.exclude"是左侧工程目录中需要排除的文件或者文件夹
4.NFS网络文件系统(可以让开发板与主机互传文件)
①sudo apt install nfs-kernel-server(在ubuntu安装NFS服务)
②配置NFS
1)sudo vim /etc/exports
2)最后添加(根据具体情况配置路径以及IP)
/home/embedfire/workdir 192.168.0.0/24(rw,sync,all_squash,anonuid=998,anongid=998,no_subtree_check)
③mkdir /home/embedfire/workdir(创建共享目录)
④sudo exportfs -arv(更新exports配置)
⑤showmount -e(查看NFS服务器加载情况)
⑥在开发板上搭建NFS文件系统
⑦sudo umount /mnt
5.交叉编译器安装(有时候存在没用的情况换4.9版本)
gcc版本选择:arch [-os] [-(gnu)eabi(hf)] -gcc
x86_64是64位,i686为32位,arch为目标芯片架构,os为操作系统,gnu为C标准库类型,eabi为应用二进制接口,hf为浮点模式
1)sudo apt install gcc-arm-linux-gnueabihf make
2)修改环境变量(根据对应情况做修改)
①sudo vi /etc/profile
②export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
3)安装工具及相关库
①sudo apt-get install lsb-core lib32stdc++6(正点原子)
②sudo apt install bison flex libssl-dev dpkg-dev lzop (野火)
6.Windows下终端登录(MobaXterm或者Xshell)
1)串口中断登录默认开启
2)网络连接与SSH登录
①开发板上电输入sudo systemctl status ssh查看ssh服务是否已经运行
②网线连接登录进去,开发板运行
(1)mv /etc/network/interfaces /etc/network/interfaces.save #重命名文件
(2)systemctl enable systemd-networkd #使能服务
(3)在/etc/systemd/network目录下增加需要配置的网卡配置信息文件,文件以.network 后缀作为结尾。如新建一个配置网卡eth1 文件eth1.network。
三、ARM启动及开发基础
1.Cortex-A架构
1)Cortex-A7运行模式
| 模式 | 说明 |
|---|---|
| User(USR) | 用户模式,非特权模式,大部分程序运行的时候就处于此模式。 |
| FIQ | 快速中断模式,进入FIQ中断异常 |
| IRQ | 一般中断模式。 |
| Supervisor(SVC) | 超级管理员模式,特权模式,供操作系统使用。 |
| Monitor(MON) | 监视模式?这个模式用于安全扩展模式。 |
| Abort(ABT) | 数据访问终止模式,用于虚拟存储以及存储保护。 |
| Hyp(HYP) | 超级监视模式?用于虚拟化扩展。 |
| Undef(UND) | 未定义指令终止模式。 |
| System(SYS) | 系统模式,用于运行特权级的操作系统任务 |
2)寄存器组
①包含低寄存器组(R0-R7)、高寄存器组(R8-R5)、堆栈指针SP、链接寄存器LR、程序计数器PC、当前程序状态寄存器CPRS、备份程序状态寄存器SPSR
②除了FIQ模式,其他工作模式共用通用寄存器。SPSR 的作用是当发生异常时备份 CPSR 的状态,也就是说 SPSR 保存的是执行异常处理函数前的 CPSR 的值。CPRS寄存器的M[4:0]为处理器模式控制位。

2.启动方式
1)启动方式选择

当mode选择10即内部boot模式时,CFG引脚设置

2)镜像组成
①Image Vector Table简称IVT,IVT里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着。

②Boot data,启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等
③Device configuration data,简称 DCD,设备配置信息,重点是 DDR3 的初始化配置
④用户代码可执行文件,比如 led.bin
imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。内部 BootROM 会将 load.imx 拷贝到 DDR 中,用户代码是要一定要从 0X87800000 这个地方开始的,因为链接地址为 0X87800000,load.imx 在用户代码前面又有 (4-1)3KByte 的 IVT+Boot Data+DCD 数据,因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400。
3.汇编基础
1)label:instruction @ comment
2)函数名:
函数体
返回语句
3)伪操作
| 指令 | 功能 |
|---|---|
| .byte | 定义单字节数据,比如.byte 0x12。 |
| .short | 定义双字节数据,比如.short 0x1234。 |
| .long | 定义一个 4 字节数据,比如.long 0x12345678。 |
| .equ | 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。 |
| .align | 数据字节对齐,比如:.align 4 表示 4 字节对齐。 |
| .end | 表示源文件结束。 |
| .global | 定义一个全局符号,格式为:.global symbol,比如:.global _start。 |
4)存储区访问指令

5)跳转指令

6)数据传输指令

7)逻辑运算指令

8)压栈和出栈指令

9)算术运算指令

4.Makefile语法基础
1)目标与依赖
[目标]:[依赖]
[命令]
2)伪目标(不期待生成目标文件)
.PHONY:[依赖]
3)使用变量
①“=”:延迟赋值,该变量只有在调用的时候,才会被赋值
②“:=”:直接赋值,延迟赋值相反,使用直接赋值的话,变量的值定义时就已经确定了。
③“?=”:若变量值为空,则进行赋值,通常用于设置默认值
④“+=”:追加赋值,可以往变量后面增加新的内容
⑤ $(变量名):调用变量
4)改造规则
①%是通配符功能类似于*
② $@代表目标
③ $<代表第一个依赖文件
④ $^表示所有的依赖文件
5)使用分支
ifeq(arg1, arg2) #若arg1与arg2值相同则为真
分支1
else
分支2
endif
6)使用函数
格式: ( 函数名参数 ) 或者 (函数名 参数)或者 (函数名参数)或者{函数名 参数}
① $ (notdir 文件名):去除文件路径中的目录部分
② $(wildcard 匹配规则):用于获取文件列表,并使用空格分隔开
③ $(patsubst 匹配规则, 替换规则, 输入的字符串):当输入的字符串符合匹配规则,那么使 用替换规则来替换字符串
④ $(foreach < var>, < list >,< text>):是把参数< list>中的单词逐一取出来放到参数< var>中,然后再执行< text >所包含的表达式。< text>所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值
5.编译下载
1)arm-linux-gnueabihf-gcc编译文件
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
其中“-g”选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字
2)arm-linux-gnueabihf-ld 链接文件
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名
3)arm-linux-gnueabihf-objcopy 格式转换
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息,最终生成led.bin文件
4)arm-linux-gnueabihf-objdump 反汇编
arm-linux-gnueabihf-objdump -D led.elf > led.dis
“-D”选项表示反汇编所有的段
5)给予烧写软件imxdownload 可执行权限:chmod 777 imxdownload
6)确定要烧写的 SD 卡:ls /dev/sd* (或者lsblk)-> 看分区找到对应卡
7)向SD卡烧写bin文件:./imxdownload led.bin /dev/sdb
四、裸机开发
1.GPIO详解
1)配置步骤
①使能GPIO对应的时钟
CMM有CCM_CCGR0~CCM_CCGR6 这 7 个寄存器,这 7 个寄存器控制着I.MX6U的所有外设时钟开关

②设置寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00,配置IO口复用功能为GPIO
③设置寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00,对IO口参数配置上下拉速度等
④配置DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR寄存器,进行状态配置,比如输入/输出、默认高低电平等
2)汇编编写初始化C环境
.global _start /* 全局标号 */
_start:/* 进入SVC模式 */mrs r0, cpsrbic r0, r0, #0x1f /* 将cpsr的模式位M[4:0]清零 */orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */ldr sp, =0X80200000 /* 设置栈指针,sp栈顶指针 */b main /* 跳转到main函数 */
3)头文件宏定义
①定义寄存器地址
//定义指向指针的指针,即指向指针数据的指针变量
#define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)
②结构体宏定义
#define CCM ((CCM_Type *)CCM_BASE)
//将基地址变成结构体指针,成员变量类型32位就4个字节递增(8位一个地址)
//位置不够用结构体数组保留位置,调用结构体CCM->CCGR0对其地址赋值
4)源文件函数定义
int main(void)
{clk_enable(); /* 使能所有的时钟 */led_init(); /* 初始化led */while(1) /* 死循环 */{ led_off(); /* 关闭LED */delay(500); /* 延时大约500ms */led_on(); /* 打开LED */delay(500); /* 延时大约500ms */}return 0;
}
//时钟使能与初始化与stm32类似
5)新建imx6ul.lds链接脚本文件
SECTIONS{. = 0X87800000;.text :{start.o main.o *(.text)}.rodata ALIGN(4) : {*(.rodata*)} .data ALIGN(4) : { *(.data) } __bss_start = .; .bss ALIGN(4) : { *(.bss) *(COMMON) } __bss_end = .;
}
6)Makefile编写
#定义变量
CROSS_COMPILE ?= arm-linux-gnueabihf- #编译器
TARGET ?= bsp #目标名字CC := $(CROSS_COMPILE)gcc #编译
LD := $(CROSS_COMPILE)ld #链接
OBJCOPY := $(CROSS_COMPILE)objcopy #格式转换
OBJDUMP := $(CROSS_COMPILE)objdump #反汇编#头文件目录,\为换行符,/为路径
INCDIRS := imx6ul \bsp/clk \bsp/led \bsp/delay
#包含 .c和.S文件
SRCDIRS := project \bsp/clk \bsp/led \bsp/delay
#调用patsubst函数给INCDIRS添加一个-I,即INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
#保存工程中所有的.s 汇编文件,dir读取路径,wildcard获取所有文件,foreach循环将SRCDIRS放入dir,并返回wildcard获取值
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
#保存工程中所有的.c 文件
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
#使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
#将编译后的.o文件放到obj文件夹下面
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS := $(SOBJS) $(COBJS) #上面两个文件集合
#指定搜索目录,样当编译的时候所需的.S 和.c 文件就会在 SRCDIRS 中指定的目录中查找
VPATH := $(SRCDIRS)
#定义一个为目标,不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行
.PHONY: clean$(TARGET).bin : $(OBJS)$(LD) -Timx6ul.lds -o $(TARGET).elf $^ #链接-Timx6ul.lds$(OBJCOPY) -O binary -S $(TARGET).elf $@ #生成.bin$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis #反汇编
#编译
$(SOBJS) : obj/%.o : %.S$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<clean:rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)
定义objs变量包含生成ledc.bin的材料:start.o和main.o,“$^”的意思是所有依赖文件的集合:start.o 和 main.o,“ $@”的意思是目标集合,在这里就是“ledc.bin”,“ $@”和 “ $<”,其中“ $<”的意思是依赖目标集合的第一个文件,相当于start.o start.s
2.中断
1)组成与概念
①STM32使用的是NVIC,IMX6ULL使用的是GIC V2中断管理器
②GIC支持8个处理器(processor0~ processor7),GIC 主要分为分发器Distributor和 CPU 接口CPUinterface/Virtual CPU interface
2)发布器
分发器用于管理 CPU 所有中断源,确定每个中断的优先级,管理中断的屏蔽和中断抢占。最终将优先级最高的中断转发到一个或者多个 CPU 接口
①SPI:SPI是共享中断,也就是我们在常用的串口中断、DMA中断等等。i.MX 6U支持 128个SPI中断请求(中断编号为 32~159)
②SGI是软件中断,中断编号为 0~15;PPI 有 16 个中断,中断编号为 16~31。SGI 与 PPI 中断都属于 CPU 私有中断,这些中断被存储在 GIC 分发器中,CPU 之间通过中断号和 CPU 编号唯一确定一个 SGI 或 PPI 中断。i.MX 6U是单核处理器,我们暂时不用过多关心 。
3)发布器编程接口

①中断使能寄存器 GICD_ISENABLERn
中断使能寄存器与中断屏蔽寄存器(GICD_ICENABLERn)是一一对应的,GIC 分发器将中断的使能与屏蔽分开设置。
(1) 计算要设置那个中断使能寄存器(假设为 n),n = m / 32。例如中断号 m = 34 则中断使能寄存器为 GICD_ISENABLER1。寄存偏移地址为 (0x100 + (4 * n)) = 0x120。
(2) 计算要设置哪一位,接步骤 ①,假设设置位为 q,则 q = m %32,m = 34, 则开启中断号为34 的中断就需要设置 GICD_ISENABLER1[2]。
②中断优先级设置寄存器 GICD_IPRIORITYRn
假设中断编号为 m,中断优先级寄存器为 n,中断优先级设置位偏移为 offset,则 n = m /4。寄存器偏移地址为 (0x400 + (4*n))。在寄存器中的偏移为offset= m%4。 以 m = 65 为例,n = 65/4 =16,所以中断优先级设置寄存器为 GICD_IPRIORITYR16,offset(n) = 65%4 = 1,中断号 65 对应的寄存器为 GICD_IPRIORITYR16[8~15].
4)CPU接口
CPU 接口可以开启或关闭发往 CPU 的中断请求,CPU 中断开启后只有优先级高于“中断优先级掩码”的中断请求才能被发送到 CPU
① CPU 接口寄存器
| 地址偏移 | 寄存器名字 | 类型 | 复位值 | 寄存器描述 |
|---|---|---|---|---|
| 0x0000 | GICC_CTLR | RW | 0x00000000 | CPU接口控制寄器 |
| 0x0004 | GICC_PMR | RW | 0x00000000 | 中断优先掩码寄器 |
| 0x0008 | GICC_BPR | RW | 0x0000000 | 中断优先级分组 |
| OxOOOC | GICC_IAR | RO | OxOOOOO3FF | 中断确认寄存器 |
| 0x0010 | GICC_EOIR | WO | • | 中断结束寄存器 |
| 0x0014 | GICC_RPR | RO | OxOOOOOOFF | 运行优先级寄存器 |
| 0x0018 | GICC_HPPIR | RO | OxOOOOO3FF | 最高优先级挂起 |
| 0x001C | GICC_ABPR | RW | 0x0000000 | GICC_BPR别名 寄存器 |
| 0x0020 | GICC_AIAR | RO | OxOOOOO3FF | GICCJAR 别名 寄存器 |
| 0x0024 | GICC_AEOIR | WO | • | GICC_EOIR 别名 寄存器 |
| 0x0028 | GICC_AHPPIR | RO | OxOOOOO3FF | GICC_HPPIR 另 名寄存器 |
| 0x00D0-0x00DC | GICC_APRn | RW | 0x00000000 | 活动的优先级寄 存器 |
| 0x00EO-Ox00EC | GICC_NSAPRnc | RW | 0x00000000 | 不安全的活动优 先级寄存器 |
| 0x00FC | GICC_IIDR | RO | 待定 | CPU接口识别寄 存器 |
| 0x1000 | GICC_DIR | WO | • | 禁用中断寄存器 |
②中断优先掩码寄存器 GICC_PMR
GICC_PMR 寄存器后 8 位(0~7)用于设置一个优先级,它的格式与GICD_IPRIORITYR 寄存器相同。设置生效后高于此优先级的中断才能发送到 CPU。需要注意的是 8 位寄存器只有高 4 位有效。
③中断优先级分组寄存器 GICC_BPR

5)CP15 协处理器
GIC 的基地址保存在 CP15协处理器中,CP15 寄存器是一组寄存器编号为 C0~c15。每一个寄存器根据寄存器操作码(opc1 和 opc2)和CRm 又可分为多个寄存器

1)CP15 寄存器只能使用 MRC/MCR 寄存器进行读、写:
①将 CP15 寄存器(c0~c15)的值读取到通用寄存器 (r0~r12):
mrc {cond} p15, <Opcode_1>, <Rd>, <CRn>, <CRm>, <Opcode_2>
②将通用寄存器 (r0~r12) 的值写回到 CP15 寄存器(c0~c15):
mcr {cond} p15, <Opcode_1>, <Rd>, <CRn>, <CRm>, <Opcode_2>
| 标签 | 含义 |
|---|---|
| cond | 指令执行的条件码,忽略则表示无条件执行命令 |
| Opcode_1 | 寄存器操作码 1 ,对应 Op1 选项。 |
| Rd | 通用寄存器,当为 mrc 时,用于保存从 CP15 寄存器读取得到的数据 |
| CRn | 要读、写的 CP15 寄存器(c0~c15) |
| CRm | 寄存器从编号 |
| Opcode_2 | 寄存器操作码 2 |
2)i.MX 6U 共享中断实现
所有外设中断(共享中断)发生时都会进入 IRQ 中断,无论是 SPI 中断、PPI 中断、还是 SGI 中断,它们都链接到了 CPU 接口,而CPU 接口接口输出到 CPU 的只有两个 FIQ(快速中断)和 IRQ。中断标号为 0~1019 的任意一个中断发生后 CPU 都会跳转到 FIQ 或 IRQ 中断服务函数去执行。在官方裸机代码中默认关闭了 FIQ,只使用了 IRQ。
3.时钟
1)PLL 与 PFD 时钟产生


①其中 32.768KHz 晶振称为外部低速时钟(CKIL),用作给RTC时钟。输出频率计算公式为 ARM_PLL = Fin * DIV_SELECT/2.0
②PLL2 与 PLL3 下方各有一组 PFD,PFD 的频率由 PLL2 或 PLL3 输出频率分频产生。PFD0 的输出频率计算公式为:PFD0_out =528*18/ PFD0_FRAC
2)根时钟生成模块 CLOCK ROOT GEN
①配置 CCSR 寄存器,将“ARM_CLK_ROOT”时钟切换到 osc_clk(24MHz)
设置 CCSR[STEP_SEL] = 0,表示选择 24MHz 的osc_clk 时钟,设置 CCSR[PLL1_SW_CLK_SEL] =1,表示选择 step_clk 时钟。
②修改 PLL1 输出时钟
③设置 CCSR[PLL1_SW_CLK_SEL] = 0,将 CPU 时钟切换到 pll1_main_clk
④修改时钟分频,设置 CACRR[ARM_PODF] = 0不分频。
4.UART串口通信
1)串口时钟与波特率
串口模块共有两个时钟输入 Peripheral Clock 和 Model Clock 。Peripheral Clock 直译为外部时钟,这个时钟主要用于读、写接收和发送的数据,例如读接收 FIFO、写发送 FIFO。Mode clock 直译为模块时钟,它既可用于接收、发送数据也用于设置波特率,这个时钟决定了串口最高支持的波特率
UART 的发送器和接收器使用相同的波特率。计算公式如下:

•BaudRate,要设置的波特率。
•Ref Freq,参考时钟,是 Mode clock 经过 RFDIV 寄存器分频后得到的频率。
•UBMR,UBMR 寄存器值。
•UBIR,UBIR 寄存器值。
2)接收、发送 FIFO
①控制单元 Control 、电源管理单元 Power Saving 以及 TxFIFO (和RxFIFO)
②TxFIFO 与RxFIFO 大小均为 32 字节,以发送为例,数据通过 UTXD 寄存器自动写入 TxFIFO, 如果 TxFIFO 没有满,则可以不断将数据写入 UTXD 寄存器。UTS[4] 寄存器是 TxFIFO 满的标志位。
3)DMA 和中断请求

5.Makefile补充
1)调用数学库用“-L”指定库所在的目录
LIBPATH := -lgcc -L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4
2)-Wall选项意思是编译后显示所有警告
3)-nostdlib 不连接系统标准启动文件和标准库文件.只把指定的文件传递给连接器
4)加入选项“-fno-builtin”表示不使用内建函数
5)添加了选项“-Wa,-mimplicit-it=thumb”,避免报错thumb(拇指?) 条件指令应该在IT(?)块中
$(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
4)加入了“-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard”指令,这些指令用于
指定编译浮点运算的时候使用硬件 FPU
$(CC) -Wall -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
结语
有关linux系统移植,见以下文章
https://blog.csdn.net/weixin_44567668/article/details/128507480
















