3.IMX6ULL裸机开发之驱动汇编实验

478 阅读4分钟

汇编驱动实验

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-input1-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

\