Linux之ARM(MX6U)裸机篇----2.汇编LED驱动实验

发布于:2025-02-11 ⋅ 阅读:(35) ⋅ 点赞:(0)

一,alpha的LED灯硬件原理分析

STM32 IO初始化流程

①,使能GPIO时钟

②,设置IO复用,复用为GPIO

③,配置GPIO的电气属性推挽,上拉下拉

④,使用GPIO,输出高/低电平

MX6ULL IO初始化

①,使能时钟,CCGR0-CCGR6这7个寄存器控制着6ULL所有外设时钟的使能,为了简单,设置CCGR0-CCGR6这7个寄存器全部为0XFFFFFFF,相当于使能所有外设时钟。

②,IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO_IO03的bit3~0设置为0101=5,这样GPIO1_IO03就复用为GPIO。

③,寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO_IO03是设置GPIO1_IO03的电气属性。包括压摆率,速度,驱动能力,开漏,上下拉等。

④,配置GPIO功能,设置输入输出,设置GPIO1_DR寄存器bit3为1,也就是设置为输出模式。设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平

二,汇编基础

_start:是汇编起始标志

LDR指令

将地址立即数加载到寄存器Rx中,@是注释符

比如LMX6UL有个寄存器GPIO1_GDIR,其地址为0x0209C004

示例:LDR R0,=0x0209C004 @将寄存器地址0x0209C004加载到R0中

示例:LDR R1,[R0]                 @读取地址0x0209C004中的数据到R1寄存器中

上述示例将寄存器GPIO1_GDIR中的值,读取到的寄存器值保存在R1寄存器中

STR指令

将一个存储器中数据写入另一个存储器Rx中

比如LMX6UL寄存器GPIO1_GDIR的值为0x20000002

示例:LDR R0,=0x0209C004 @将寄存器地址0x0209C004加载到R0中

示例:LDR R1,   =0x20000002 @R1保存要写入到寄存器的值,R1=0x20000002

示例:STR R1,   [R0]                @将R1的值写入到R0中所保存的地址中

@用汇编实现int a,b  a=b   假设a地址为0x20,b地址为0x30
LDR R0, =0X30   @读取b的值到R0中
LDR R1, [R0]    @读取R0的值到R1中
LDR R0, =0X20   @读取a的值到R0中
STR R1, [R0]    @将R1的值写到R0中

可以用小写,ldr,str等

三,编译程序

①,将.c .s文件变为.o文件

②,将所有.o文件连接为.elf格式的可执行文件

③,将.elf文件转化为bin文件

④,将.elf文件转为汇编,反汇编

链接:要设置链接的起始地址,也就是代码保存的起始地址。

对于 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内部bootrom会从SD卡,EMMC 等外
置存储中读取头部信息,然后初始化 DDR,并且将 bi 文件拷贝到指定的地方。“
Bin 的运行地址一定要和链接起始地址一致。位置无关代码除外。

点灯实验链接起始地址为0X87800000

第①步指令 arm-linux-gnueabihf-gcc -g -c led.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   //.dis文件用于分析调试代码

可以编写makefile执行全部指令

点灯程序如下:

.global _start @全局标号

_start:
    /*使能所有外设时钟*/
    ldr r0, =0x020c4068 @CCGR0
    ldr r1, =0xffffffff @要向CCGR0写入的数据
    str r1, [r0]        @将0xfff写入到CCGR0中

    ldr r0, =0x020c406c @CCGR1
    str r1, [r0]        @将0xfff写入到CCGR1中

    ldr r0, =0x020c4070 @CCGR2
    str r1, [r0]        @将0xfff写入到CCGR2中

    ldr r0, =0x020c4074 @CCGR3
    str r1, [r0]        @将0xfff写入到CCGR3中

    ldr r0, =0x020c4078 @CCGR4
    str r1, [r0]        @将0xfff写入到CCGR4中

    ldr r0, =0x020c407c @CCGR5
    str r1, [r0]        @将0xfff写入到CCGR5中

    ldr r0, =0x020c4080 @CCGR6
    str r1, [r0]        @将0xfff写入到CCGR6中



    /* 配置GPIO1_IO03_PIN的复用为GPIO,也就是设置
     * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03=5
     * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器的地址为0x020E0068
     */
    ldr r0, =0x020E0068 @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
    ldr r1, =0x5        @要写入的数据
    str r1, [r0]        @将5写入到IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03中



    /* 配置GPIO1 I003的电气属性 也就是寄存器:
     * IOMUXC SW PAD CTL PAD GPIO1 IO03
     * IOMUXC SW PAD CTL PAD GPIO1 I003寄存器地址为0x020e02f4
     * bit0:0    低速率
     * bit5:3:   110 RO/6驱动能力
     * bit7:6:   10 100MHz速度
     * bit11:    0 关闭开路输出
     * bit12:    1 使能pull/kepper
     * bit13:    0 kepper
     * bit15:14:00 100K下拉
     * bit16:    0 关闭hys
     */
    ldr r0, =0x020e02f4
    ldr r1, =0x10b0
    str r1, [r0]



    /* 设置GPIO
     * 设置GPIO1_GDIR寄存器,设置GPI01_GPI003为输出
     * GPI01_GDIR寄存器地址为0x0209c004,设置GPI01 GDIR寄存器bit3为1,
     * 也就是设置GPIO1 I003为输出。
     */
    ldr r0, =0x0209c004
    ldr r1, =0x8
    str r1, [r0]



    /* 打开LED,也就是设置GPIO1_IO03为0
     * GPIO1_DR寄存器地址为0x0209c000
     */
    ldr r0, =0x0209c000
    ldr r1, =0
    str r1, [r0]

loop:          @死循环
    b loop     @b是跳转,该句是跳转得到loop



@要多空几行,避免报错

四,烧写bin文件

STM32 烧写到内部 FLASH。
6ULL支持 SD 卡、EMMC、NAND、nor、SPlflash 等等启动。裸机例程选择烧写到 SD(tf卡)卡里面

sd卡要格式化,能支持FAT32格式

在 ubuntu 下向 SD 卡烧写裸机 bin 文件。烧写不是将 bin 文件拷贝到 SD 卡中,而是将
bin 文件烧写到 SD 卡绝对地址上。而且对于1.MX而言,不能直接烧写 bin 文件,比如先在
bin 文件前面添加头部。

该实验中将官方ddr初始化文件和点灯程序一起编译,用dd指令就能烧录

指令:sudo dd main.bin /dev/sdf 


网站公告

今日签到

点亮在社区的每一天
去签到