3.裸机汇编LED驱动实验

汇编驱动实验

1.汇编LED原理分析

ARM中汇编的作用

​ Cotex-A系列需要自己写汇编。但是指令不是很多,只需要初始化一些外设。只需要1-2个重要的外设,看门狗,紧接着初始化DDR。设置好指针就能运行C语言了。

​ STM32的芯片不需要写汇编,是因为ST昌吉已经帮你写好了,就是那个.s文件。

/*
为什么要学习Cortex-A汇编
1.需要用汇编初始化一些SOC外设
2.使用汇编初始化DDR
	但是6ULL芯片不需要,会在bin头中包含这些内容
3.设置SP指针一遍指向DDR,设置好C语言运行环境。
*/

开发版LED灯硬件原理分析

	STM32 的IO初始化流程

​	1.使能GPIO时钟
​	2.设置IO复用,复用为GPIO
​	3.配置GPIO的电气属性
​	4.使用GPIO输出高低电平
	
	I.MX6ULL 的初始化流程
​	1.使能时钟(CCM的 CCGR0-CCGR6这七个寄存器)为了简单,设置CCGR0-CCGR6这七个寄存器全部为0xFFFFFFFF , 相当于使能全部的时钟。
​	2.IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的[3,0]位设置为0101,这样GPIO1_IO03就可以复用为GPIO模式了。
​	3.配置电气属性,将寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的电气属性
	设置的重点是压摆率,速度,驱动能力,开漏,上下拉等电阻。
​	4.配置GPIO功能,设置输入输出功能。
        GPIOx_DR的读写寄存器,可以读取数据,也可以输入数据
        GPIOx_GDIR的寄存器,代表输入输出0-input , 1-output
        GPIOx_PS的状态寄存器
        GPIOx_ICR的中断触发寄存器
        GPIOx_ISR的中断掩码寄存器,控制中断时使能还是关闭
	设置GPIO_DR=1为输出模式,就能点亮小灯了。

2.汇编简介

​ 想要详细地去学习汇编,就要去参考《ARM Architecture Regerence Manual ARMx7-A and …-R edition》与《ARM Core Cotex-A(armV7)编程手册》

​ 使用GNU汇编语法

@C代码示例
int a , b		
a=b
@assembly示例
LDR R0 , =0X20	
LDR R1 [R0]		@将R0的数据写到R1中

LDR R0 , =0X30
STR R1 ,[R0]	@将R1的数据写到R0地址中
@压栈出栈
PUSH 	{r0~R3,r5}
PUSH	{LR}

POP		{LR}
POP 	{r0~R3,r5}

Cotex-A内部有9中状态

​ 我们需要知道的是User , SVC , System ,FIQ , RIQ , Abort

寄存器

​ R0-R12 , SP , LR . PC ,CPSR (特殊寄存器),SPSR(异常备份寄存器)

3.点亮LED汇编


.global _start /*全局标号*/

_start:
	/*使能GPIO1_IO04  ---- RED LED */
	/*CCGR1*/
	ldr r0 , =0x020c406c	
	ldr r1 , =0xffffffff    /*[27,26]*/
	str r1 , [r0]

	
	/*IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04寄存器复用GPIO*/
	ldr r0 , =0x020e006c
	ldr r1 , =0x5
	str r1 , [r0]
	
	/*IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO04电气特性配置
	 *[0]bit : 0 低压摆率
	 *[5:3]bit :110 R0/6驱动能力
	 *[7:6]bit :10	速度100MHz	
	 *[11]bit  :0	关闭开路输出
	 *[12]bit  :1	pull/keeper使能
	 *[13]bit  :0	keeper功能
	 *[15:14]bit:00 默认下拉
	 *[16]bit  :0	HYS关闭
	 */
	
	ldr r0 , =0x020e02f8
	ldr r1 , =0x10b0
	str r1 , [r0]
	
	/*GPIO1_GDIR寄存器*/
	ldr r0, =0x0209C004
	ldr r1, =0x0000010
	str r1,[r0]
	
	/*GPIO1_IO4输出低电平*/
	ldr r0 , =0x0209c000
	ldr r1 , =0
	str r1 , [r0]
/*进入死循环*/
loop:
	b loop

4.编译程序

​ 用交叉编译工具链去编译程序

​ 1.使用arm-none-linux-gnueabi-gcc将.s文件变为.o

​ 2.将.o文件链接为.elf可执行文件,它比bin文件多了一些信息。链接是为了将.o文件添加到一个指定的起始地址,指向RAM,才能一行一行读取文件。RAM分为内部RAM128kb(0x900000-0x91ffff),与外部RAM512M(0x80000000-0x91ffffff)。我们选择链接起始地址为0x87800000。

​ 3.将elf文件转为bin文件

​ 4.将elf文件转为汇编,反汇编

​ 我们的裸机程序并没有初始化DDR。要初始化DDR,需要添加一个头部信息。头部信息包含了DDR的初始化参数。I.MX系列SOC内部的boot room会从SD卡,EMMC等外部存储中读取头部信息,然后初始化DDR,并且将Bin文件拷贝到指定地方。

​ bin的运行地址一定要和链接其实地址一致,位置无关代码除外。

#编译为预编译文件
$: arm-none-linux-gnueabihf-gcc -g -c led.s -o  led.o
#链接
$: arm-none-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
$: ls
led.s led.o led.elf
#转为bin文件
$: arm-none-linux-gnueabihf-objcopy -O binary -g -S led.elf led.bin
$: ls
led.s led.o led.elf led.bin
#还可以实现反汇编
arm-none-linux-gnueabihf-objdump -D led.elf > led.dis

5.烧写bin文件

​ IMX6ULL支持SD,EMMC,NAND,NOR FLASH,SPI Flash启动。

裸机例程那么使用SD卡吧。但是并不是直接把.bin文件直接扔到SD卡内存中。

将download二进制文件使用方法。

​ 它其实是讲bin文件加入头部的.imx文件下载到了SD卡中去读取。

$: ./download led.bin /dev/sdb

这样插入SD卡就可以看到LED红灯被点亮了。

6.Makefile

​ 由于常常需要烧写,不断写那几个shell命令太麻烦了,写一个makefile吧

FILE=led

$(FILE).bin : $(FILE).s
	arm-linux-gnueabihf-gcc -g -c $(FILE).s -o $(FILE).o
	arm-linux-gnueabihf-ld -Ttext 0x87800000 $(FILE).o -o $(FILE).elf
	arm-linux-gnueabihf-objcopy -O binary -g -S $(FILE).elf $(FILE).bin
#arm-linux-gnueabihf-objdump -D $(FILE).elf > $(FILE).dis  

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

你可能感兴趣的:(IMX6ULL学习手册)