【Linux学习】基础篇 2.2正点原子裸机 汇编LED实验实现

        通过上一篇基础篇2.1基本了解使用汇编程序编写点亮一个LED等的思想和步骤,接下来具体实现步骤。

硬件原理分析

        LED0 接到了 GPIO_3 上,GPIO_3 就是 GPIO1_IO03,当 GPIO1_IO03 输出低电平(0)的时候发光二极管 LED0 就会导通点亮,当 GPIO1_IO03 输出高电平(1)的时候发 光二极管 LED0 不会导通,因此 LED0 也就不会点亮。所以 LED0 的亮灭取决于 GPIO1_IO03 的输出电平,输出 0 就亮,输出 1 就灭。

MAX6ULL  IO口初始化流程:

参考手册章节30

1.使能时钟,CCGR0-CCGR6这七个寄存器控制这6ULL所有外设时钟的使能,为了简单化,设置CCGR0-CCGR6这7个寄存器全部为0XFFFFFFFF ,相当于使能所有外设时钟

2.IO复用,将寄存器的IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的bit3-0设置为0101=5,此时GPIO_IO03配置为复用功能

3.将寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03是设置GPIO_IO03的电气属性

  包括压摆率,速度,驱动能力,开漏,上下拉等。

4.配置GPIO功能,设置输入输出,设置GPIO_GDIR寄存器bit3为1,即设置为输出模式

5.设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平。

创建VS Code工程

        vscode 文件夹里面存放 VSCode 的工程文件,新建汇编文件led.s ,  led.s 这个文件中编写汇编程序。使用 VSCode 打开 1_leds 这个文件夹

 VS Code内编写代码实现:


.global _start @全局标号

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

    ldr r0,=0x020c406C  @CCGR1地址
    str r1, [r0]        @将0xffffffff写入到CCGR1中

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

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

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

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

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

/*配置GPIO_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中

/*配置GPIO_IO03 的电气属性 即寄存器
*IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的地址为0x020e02f4
*bit0:     0    低速率
*bit 5:3 :   110   R0/6驱动能力
*bit 7:6 :   10    100Mhz速度
*bit11:     0     关闭开路输出
*bit12:      1      使能pull/kepper
*bit13:   0       kepper
*bit15:14:  00     100K下拉
*bit16:      0     关闭hys
计算得出十六进制为10B0*/
    ldr r0,=0x020e02f4  @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
    ldr r1,=0x10b0      @要写入的数据
    str r1, [r0]        @将5写入到IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03中

/* 设置GPIO
  设置GPIO1_GDIR寄存器,设置GPIO1_GPIO03为输出
   设置GPIO1_GDIR寄存器0x0209c004,设置GPIO1_GDIR寄存器bit3为1
   即设置GPIO1_IO03为输出
 */
    ldr r0,=0x0209c004  @设置GPIO1_GDIR寄存器
    ldr r1,=0x8         @要写入的数据
    str r1, [r0]        
/*打开LED,即设置GPIO1_IO03为0
  GPIO1_DR寄存器地址为0x0209c000
 */
    ldr r0,=0x0209c000  @设置GPIO1_GDIR寄存器
    ldr r1,=0            @要写入的数据
    str r1, [r0]        

loop:  
    b loop

程序编译步骤:

1.arm-linux-gnueabihf-gcc 编译文件,将.c.s文件变为.o  --

终端输入例:arm-linux-gnueabihf-gcc -g -c leds.s -o led.o

2.arm-linux-gnueabihf-ld 链接文件,将所有的.o文件连接为elf格式的可执行文件

终端输入例:arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

注意:led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件,因此还 需要将 led.elf 文件转换为.bin 文件

3.arm-linux-gnueabihf-objcopy 格式转换,将elf文件转为bin文件

终端输入例:arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

4.arm-linux-gnueabihf-objdump 反汇编,将elf文件转为汇编,反汇编

终端输入例:arm-linux-gnueabihf-objdump -D led.elf > led.dis

 逐行输入指令较麻烦,建议直接创建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

链接的解释:

        链接就是将所有.o文件链接在一起,并且链接到指定的地方。 本实验链接时要指定链接起始地址。链接起始地址就是代码运行的起始地址。

       对于6ULL来说,链接起始地址应该指向RAM地址,RAM分为内部RAM和外部RAM也就是DDR,6ULL内部的RAM地址范围0X900000~0X91FFFF。也可以放在外部DDR中,对于I.MAX-ALPHA开发板,512MB字节DDR版本的核心板,DDR范围就是0X80000000-0X9FFFFFFF。对于256MB的DDR核心板,范围为0X80000000-0X8FFFFFFF

裸机代码链接起始地址为0X87800000(便于后续uboot链接地址)。要使用DDR,必须要初始化DDR,bin文件不能直接烧写到SD卡、EMMC、NAND等外置储存中,然后从外置储存中启动运行。而不是bin文件不能直接运行,使用JLINK将bin文件直接下载到内部RAM中还是可以运行。

       i.max系列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.MAX而言,不能直接烧写bin文件,比如先在bin文件前面添加头部,完成改工作,需要正点原子提供imxdownload软件

 1.将 imxdownload 拷贝到工程根目录下

2.给予 imxdownload 可执行权限

        直接将软件 imxdownload 从 Windows 下复制到 Ubuntu 中以后,imxdownload 默认是 没有可执行权限的,给予imxdownload可执行权限:chmod 777 imxdownload

 

 3.确定SD卡:

        Ubuntu 下所有的设备文件都在目录“/dev”里面,所以插上 SD 卡以后也会出现在“/dev” 里面,其中存储设备都是以“/dev/sd”开头的。将SD卡接入读卡器再接入Ubuntu系统,输入命令,通过插拔对比多出的设备即为SD卡外设。

 因此SD卡设备名称为/dev/sdb

4.向 SD 卡烧写 bin 文件

烧写命令:./imxdownload led.bin  /dev/sdb // <led.bin为烧写的bin文件;/dev/sdb为烧写的SD卡   >

该操作后:Imxdownload会向led.bin添加一个头部,生成新的load.imx文件,这个load.imx文件就是最终烧写到SD卡里面。

代码验证:

         烧写完成,准备就绪后,从读卡器取出SD卡,插入开发板中,并将拨码开关设置为SD卡启动模式。

LED0灯成功被点亮,代码运行正常!!最难点灯,跨出一大步~

目前遇到的最难点灯步骤,那么能否通过JLINK直接烧写程序?

答:不可以,6ULL支持JTAG,因为没有烧写算法,所以无法烧写,但可以通过JTAG将bin文件下载到内部ram,6ULL的JTAG口与SAI复用,SAI连接了WM8960音频DAC。在嵌入式Linux开发中基本不用JLNK

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值