I.MX6ULL嵌入式开发笔记--LED汇编点灯篇

  I.MX6U-ALPHA的裸机开发初学笔记,此文章适合想要开始学习Linux驱动开发的朋友,内容简单,想要更加深入了解的可以观看正点原子的相关视频。

一、ARM汇编基础

  与STM32单片机不同,stm32开发板的启动文件中已经将SP指针初始化、DDR初始化。正点原子的Linux开发板并没有初始化这些,所以C语言环境还没准备好,不能直接运行C语言代码,我们利用汇编语言将C语言环境搭建好后就可以执行C语言代码了。这里刚开始只介绍了两个常用并且十分重要的指令,LDR、STR。他们是存储器访问指令,由于ARM不能直接的访问存储器,所以一般是我们将需要配置的值先保存到寄存器中,然后借助存储器访问指令将通用寄存器的的配置数据写入到I.MX6LL寄存器中。

1、LDR指令

1 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
2 LDR R1, [R0] @读取地址 0X0209C004 中的**数据**R1 寄存器中

2、STR指令

1 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
2 LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
3 STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

  需要注意的是这两个指令都是操控32位数据。如果需要按照字节与半字进行操作的话需要给LDR、STR后面分别加上B或者H。LDRB、LDRH。

下面举一个非常简单的例子:

int a,b;
a=b;
假设a地址为0X20,b地址为0x30

LDR R0, =0X30   //将b的地址写入到寄存器R0
LDR R1, [R0]    //将寄存器R0中所存地址对应的值(b),写入到R1

LDR R0, =0X20   //将a的地址写入到寄存器R0
STR R1, [R0]    //将R1中的值(b) 写入到 R0 中所保存的地址中

二、汇编LED点灯

  点灯是单片机的灵魂,跟各类编程语言当中的 " Hello World! "有着同样重要的地位!!!
  以下是根据原子给的视频讲解所列笔记:

STM32 IO初始化流程:
	①、使能GPIO时钟。
	②、设置IO复用,将其复用为GPIO
	③、配置GPIO的电气属性。
	④、使用GPIO,输出高/低电平。

I.MX6ULL IO初始化:
	①、使能时钟,CCGR0~CCGR6这7个寄存器控制着6ULL所有外设时钟的使能。为了简单,设置CCGR0~CCGR6这7个寄存器全部为0XFFFFFFFF,相当于使能所有外设时钟。
	②、IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的bit3~0设置为0101=5,这样GPIO1_IO03就复用为GPIO。
	③、寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03是设置GPIO1_IO03的电气属性。包括压摆率、速度、驱动能力、开漏、上下拉等。
	④、配置GPIO功能,设置输入输出。设置GPIO1_DR寄存器bit3为1,也就是设置为输出模式。设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平。

  下面就是具体初始化的代码,都是通过控制寄存器上每个位来实现初始化。

.global _start /* 全局标号 */
 
 /*
 * 描述: _start 函数,程序从此函数开始执行此函数完成时钟使能、
 * GPIO 初始化、最终控制 GPIO 输出低电平来点亮 LED 灯。
 */
 _start:
 /* 例程代码 */
 /* 1、使能所有时钟,一共有七组 */
 ldr r0, =0X020C4068 /* 寄存器 CCGR0 */
 ldr r1, =0XFFFFFFFF 
 str r1, [r0] 
 
 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]
 
 
 /* 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

三、编译程序

①、使用arm-linux-gnueabihf-gcc,将.c .s文件变为.o
②、将所有的.o文件连接为elf格式的可执行文件。
③、将elf文件转为bin文件。
④、将elf文件转为汇编,反汇编。

链接:
链接就是将所有.o文件链接在一起,并且链接到指定的地方。本实验链接的时候要指定链接起始地址。链接起始地址就是代码运行的起始地址。
对于6ULL来说,链接起始地址应该指向RAM地址。RAM分为内部RAM和外部RAM,也就是 DDR。6ULL内部RAM地址范围0X900000~0X91FFFF。也可以放到外部DDR中,对于I.MX6U-ALPHA开发板,512MB字节DDR版本的核心板,DDR范围就是0X80000000~0X9FFFFFFF。对于256MB的DDR来说,那是0X80000000~0X8FFFFFFF。
	正点原子系列视频,裸机代码的链接起始地址为0X87800000。要使用DDR,那么必须要初始化DDR,对于I.MX来说bin文件不能直接运行,需要添加一个头部,这个头部信息包含了DDR的初始化参数,I.MX系列SOC内部boot rom会从SD卡,EMMC等外置存储中读取头部信息,然后初始化DDR,并且将bin文件拷贝到指定的地方。
	Bin的运行地址一定要和链接起始地址一致。位置无关代码除外。

四、烧写bin文件

  STM32烧写到内部FLASH。
  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卡里面去的。

如果烧写过程中一遍一遍输指令过于麻烦可以通过Makefile脚本来完成,Makefile语法在这里就不过多说明了。

led.bin : leds.s
	arm-linux-gnueabihf-gcc -g -c leds.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-gnueabihf-objdump -D led.elf > led.dis

clean:
	rm -rf *.o led.bin led.elf led.dis

五、结果验证

首先将BOOT_CFG调节成SD卡启动
在这里插入图片描述

上电复位之后小灯成功被点亮
在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值