本开发学习笔记以正点原子ALPHA开发板作为学习开发板,i.MX6ULL为其CPU。
主要学习步骤跟随https://beta.yuanzige.com/course/detail/50090中的视频进行学习,其中前期工作已经学习并准备完成,包括了学习视频的【第一期】手把手教你学Linux之Ubuntu入门篇全部内容和【第二期】手把手教你学Linux之ARM(MX6U)裸机篇中的前5讲内容,之后的笔记将从第二期视频的第6讲开始学习。
1. LED点亮实验(GPIO驱动)
1.1 汇编实现LED
1、使能函数的时钟寄存器:CCGR0对应的IO时钟 (CCM Clock Gating Register 1 (CCM_CCGR1)、27–26(CG13)表示gpio1 clock gpio1_clk_enable));
2、映射IO口功能:将寄存器(IOMUXC_SW_MUX _ CTL_PAD_GPIO1_IO03)的0-3bit设置为下图
3、配置IO的电气属性:(IOMUXC_SW_ PAD_CTL_PAD_GPIO1_IO03),在配置时需参考下图设置:
主要包括压摆率(SRE)、速度(SPEED)、驱动能力(DSE)、开漏输出(ODE)、上下拉(PUS)等
压摆率表示为从0到1的变化快慢、快为高压摆率、低为低压摆率;
速度为输出时的速度;
驱动能力用所带的负载的大小表示;
4、配置GPIO的功能(数据位、输入输出、中断触发方式、中断使能、中断状态)
在本节中需设置GPIO1_GDIR的Bit3为输出模式,即置为1;
设置GPIO1_DR的Bit3的输出电平,0为低电平、1为高电平;
1.2 汇编简单回顾
常用指令:
1、处理寄存器内部寄存器: MOV 等
2、处理CPU RAM中的寄存器操作:
LDR Rd, [Rn , #offset] 表示 从存储器Rn+offset的位置读取数据存放到 Rd中。
STR Rd, [Rn, #offset] 表示 将Rd中的数据写入到存储器中的 Rn+offset位置。
**LDR:从存储器中读取数据到内部寄存器Rx中**
***LDR R0, =0X0209C004*** @将寄存器地址0X0209C004加载到R0中,即R0=0X0209C004
***LDR R1, [R0]*** @读取地址0X0209C004中的数据到R1寄存器中
**STR:将内部寄存器Rx的数据写到存储器中**
***LDR R0, =0x0209c004*** @将寄存器地址0X0209C004加载到R0中,即R0=0X0209C004
***LDR R1, =0x20000002*** @R1保存要写入到寄存器的值,即R1=0X20000002
***STR R1, [R0]*** @将R1中的值写入到R0中所保存的地址中
3、跳转操作: B(跳转到某一段代码之后不会再回来)、BL(跳转到某一段代码之后仍可再回来)
1.3 代码编写
编写出来代码如下,相关内容已在注释中说明清楚
/**
* Copyright @ JianshuZhao Co., Ltd. 2019-2049. All rights reserved.
* Name:led.s
* Description:学习Linux开发的实验程序
* Function: 点亮开发板上的LED灯
* Author:JianshuZhao
* Version:V1.0.0
* Date:2020.2.16
*/
.global _start @全局标号
_start:
/* Enable Clock; */
ldr r0, =0x020c4068 @CCGR0
ldr r1, =0xffffffff
str r1, [r0] @write 0x020c406c to r1
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]
/* Config PIN MUX */
ldr r0, =0x020e0068 @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
ldr r1, =0x5
str r1, [r0] @write 0x020c406c to r1
/* Config PIN PAD
* bit0: 0 低速率
* bit5-3: 110 R0/6驱动能力
* bit7-6: 10 100MHz速度
* bit11: 0 关闭开路输出
* bit12: 0 使能上下拉/保持
* bit13: 0 保持
* bit15-14: 00 100K下拉
* bit16: 0 关闭hys
*/
ldr r0, =0x020e02f4 @IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
ldr r1, =0x10b0
str r1, [r0] @write 0x020e02f4 to r1
/* Config GPIO bit3 to 1, means output*/
ldr r0, =0x0209c004 @GPIO direction register (GPIO1_GDIR)
ldr r1, =0x8
str r1, [r0] @write 0x0209c004 to r1
/* Open led , set GPIO1_IO03_DR to 0*/
ldr r0, =0x0209c000 @GPIO data register (GPIO1_DR)
ldr r1, =0x0
str r1, [r0] @write 0x0209c000 to r1
loop:
b loop
1.4 编译程序
1、arm-linux-gnueabihf-gcc -g -c led.s -o led.o
其中-g表示产生调试信息、-c表示编译源文件,但是不链接,-o表示生成的文件名称
2、arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
其中,链接时需指定起始地址,即代码运行的起始地址;
链接起始地址应指向RAM地址,分为内部RAM(0x900000—0x91FFFF)和外部RAM(DDR,在正点原子开发板中(512M,范围为0x800000—0x9FFFFFFF)),在之后的开发,使用0x87800000作为链接的起始地址。
在I.MX中,Bin文件除非使用jlink下载至内部RAM中运行,否则不能直接运行,必须使用头部文件。I.MX系列SOC内部有提供BootLoader,从外部存储中读取内部信息,然后初始化DDR,并将.bin文件拷贝到指定的地方。bin的运行地址一定要和链接地址一致。
3、arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
将led.elf文件转换成led.bin,其中 -O表示以什么格式(binary)输出,-S表示不要复制源文件中的重定位和符号信息,-g表示不复制源文件中的调试信息
4、arm-linux-gnueabihf-objdump -D led.elf > led.s
反汇编
最终三条命令执行完成之后输出如下内容
下载程序、
因暂时没有SD卡,明天再说。