LED驱动实验

这篇博客详细介绍了如何使用Cortex-A汇编进行LED驱动实验,包括STM32和I.MX6ULL的初始化流程。内容涵盖汇编代码的编写、编译、链接、烧写bin文件的过程,以及如何处理链接错误。还涉及了makefile的使用,C语言版本的LED驱动实验,并讲解了链接脚本的编写和内存布局,以及Jlink的使用场景。
摘要由CSDN通过智能技术生成

汇编

1、为什么要学习Cortex-A汇编:

  • 需要用汇编初始化一些SOC外设。
  • 使用汇编初始化DDR,I.MX6U不需要。
  • 设置sp指针,一般指向DDR,设置好C语言运行环境。

2、使用指南

  • 类似ldr这种可以用大写,也可以小写。但用了大写就全部大写,用了小写就全部小写。

有arm内核寄存器还有存储器中的寄存器

初始化流程

LED接在GPIO1_IO03上,低电平点亮
1、stm32

  • 使能GPIO时钟。
  • 设置IO复用,将其复用为GPIO(pin默认就是GPIO功能,如果要用到pin其他动能就要先设置复用。比如将PA9复用为USART1_TX)
  • 配置GPIO的电气属性。
  • 使用GPIO,输出高/低电平。

2、I.MX6ULL IO初始化:

  • 使能时钟(在章节18),CCGR0-CCGR6这7个寄存器控制着6ULL所有外设时钟的使能。为了简单,设置CCGR0~CCGR6这7个寄存器全部为0XFFFFFFFF,相当于使能所有外设时钟。其实GPIO1_IO03,开启CCGR1的27-26位就行了,给他设置11
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  • IO复用,将寄存器IOMUXC_SW_MUXCTL_PAD GPIO1_IO03的bit3~0设置为0101=5,这样GPIO1_IO03就复用为GPIO。
    在这里插入图片描述在这里插入图片描述

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

	/*寄存器SW_PAD_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 低转换率
	 */

  • 配置GPIO功能(第28章),设置输入输出。设置GPIO1_GDR寄存器bit3为1(也就是第四位,因为有IO0),也就是设置为输出模式。设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平(如果设置为了输入,那就是读DR寄存器)。(注意:led实验用到的端口是GPIO1_IO3,因此这里选择的是GPIO1的地址 然后是第三位bit3)
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

makefile讲解

1、系统变量
2、自定义变量

  • =,延迟赋值。等到调用的时候赋值。
  • :=,立即赋值
  • ?=,空赋值
  • +=,追加赋值

3、自动化变量

  • $<,第一个依赖文件
  • $^,全部的依赖文件
  • $@,表示目标

视频讲解

汇编代码书写

编写驱动

.global _start  /* 全局标号 */

/*
 * 描述:	_start函数,程序从此函数开始执行此函数完成时钟使能、
 *		  GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
 */
_start:
    /*1、时钟使能 我们这里为了方便给他们都使能了*/
    ldr r0,=0x020c4068 @CCGR0的寄存器地址
    ldr r1,=0xffffffff @要写入的数据 共32位,全部写1 也就是全部使能
    str r1,[r0]        @将r1写到r0中 也就是写入到寄存器中

    @主播是把CCGR0-6都全部使能了。我查阅手册发现,GPIO3是CCGR1,其实只需要这个的27-26位使能就行了
    ldr r0,=0x020c406c @CCGR1
    str r1,[r0] 

    /*2、设置GPIO1_IO03复用为GPIO1_IO03
    时钟使能 我们这里为了方便给他们都使能了*/
    ldr r0,=0x020e0068
    ldr r1,=0x5
    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为输出 只需要设置bit3为1就行*/
    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  @b就是跳转的意思,这样就是不断的跳转到loop

编译

1、使用arm-linux-gnueabihf-gcc,将.c .s文件变为.o

arm-linux-gnueabihf-gcc -g -c leds.s -o led.o
  • 上述命令就是将 led.s 编译为 led.o
  • 其中 “-g” 选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c” 选项是编译源文件,但是不链接。“-o” 选项是指定编译产生的文件名字 led.o。执行上述命令以后就会编译生成一个 led.o 文件
  • .o文件也叫作目标文件object,是一个二进制文件

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

  • 链接就是将所有.o文件链接在一起,并且链接到指定的地方(也就是确定了执行地址,代码运行的时候所处的地址。还有“存储地址”就是可执行文件存储在哪里,比如这里就是存储在SD卡中,可执行文件的存储地址可以随意选择)。本实验链接的时候要指定链接起始地址。链接起始地址就是代码运行的起始地址。
  • 对于6ULL来说,链接起始地址指向RAM地址。RAM分为内部RAM(6ULL内部有rom但是我们用不了,几乎所有cotex-A的芯片内部都没有flash,所以不能存在内部flash)和外部RAM(也就是 DDR)。6ULL内部RAM地址范围0X900000-0X91FFFF。也可以放到外部DDR中,对于I.MX6U-ALPHA开发板,512MB字节DDR版本的核心板,DDR范围就是0X80000000- 0X9FFFFFFF(这里的1就是1byte,0x9FFFFFFF+1-0X8000000的值转为十进制/1024/1024=512MB)。对于256MB的DDR来说,那就0X80000000~0X8FFFFFFF。
  • 之所以选择 0X87800000 这个地址是因为后面要讲的 Uboot 其链接地址就是 0X87800000,这样我们统一使用 0X87800000 这个链接地址,不容易记混。
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
  • 上述命令中-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里我们命名为 led.elf。上述命令执行完以后就会在工程目录下多一个 led.elf 文件
  • 注意这里的-ld 与-Ttext之间存在一个空格

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

  • led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件
  • 本系列视频,裸机代码的链接起始地址为0X87800000。要使用DDR,那么必须要初始化DDR,对于I.MX来说bin文件不能直接运行(严格的来说,应该是bin文件不能直接烧写到SD卡、EMMC/NAND等外置存储中,然后从这些外置存储中启动运行。而不是bin文件不能直接运行,使用Jlink将bin文件直接下载到内部RAM中还是可以运行的),需要添加一个头部,这个头部信息包含了DDR的初始化参数,I.MX系列SOC内部boot rom会从SD卡,EMMC等外置存储中读取头部信息,然后初始化DDR,并且将bin文件拷贝到指定的地方。
  • Bin的运行地址一定要和链接起始地址一致。位置无关代码除外。
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
  • 上述命令中,“-O” 选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。

4、将elf文件转为汇编,反汇编。
大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,
因此就需要进行反汇编,一般可以将 elf 文件反汇编。

arm-linux-gnueabihf-objdump -D led.elf > led.dis
  • 上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一
    个名为 led.dis 文件
    在这里插入图片描述
    从图 可以看出 led.dis 里面是汇编代码,而且还可以看到内存分配情况。在0X87800000 处就是全局标号_start,也就是程序开始的地方。通过 led.dis 这个反汇编文件可以明显的看出我们的代码已经链接到了以 0X87800000 为起始地址的区域。

烧写bin文件

烧写软件就是在b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成草

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值