I.MX6ULL——点亮一个LED
本文最后更新于 111 天前,其中的信息可能已经有所发展或是发生改变。

我们今天分享如何用裸机开发,点亮I.MX6ULL;我使用的是正点原子阿尔法IMX6ULL开发板,EMCC版本,目前还是处于学习中。

作为点灯大师,万里长征第一步从点灯开始。

如何点亮LED

我们在编写STM32点灯代码时候,第一步要做的是了解需要点亮哪一个灯,查看原理图找到LED的连接引脚和什么样的输出状态才能让LED点亮。

我们找到正点原子的原理图,找到LED的部分,发现其的LED是与GPIO0_IO03连接,当属于引脚输出低电平时候点亮。

配置引脚

我们对比STM32使用标准库对一个GPIO引脚初始化的代码,

void LED_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能 PB 端口时钟
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PB5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度
 GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化 GPIOB.5
 
 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
}

可以发现STM32初始化引脚分为

  • 初始化时钟
  • GPIO配置
  • GPIO是否使用复用功能
  • GPIO输出电平

那么很显然,我们要用的IMX6ULL和STM32的步骤是相同的,下面我们就开始照着官方参考手册一行行写汇编。

配置部分

初始化时钟

查找官方参考手册,寻找“Clock Controller Module”(时钟控制模块),在该目录下有我们所用的寄存器

我们就拿CCM Clock Gating Register 0 (CCM_CCGR0)进行分析,在手册中是这样介绍的“These bits are used to turn on/off the clock to each module independently. The following table details the possible clock activity conditions for each module”大概跟大家翻译一下,这些位都是可以独立控制模块时钟的使能的,下面就是它的详细介绍。

可以看到我们有3种状态,2个位表示:

  • 00:时钟使能的
  • 01:时钟只在运行的时候启动,等待或停止模式下是不使能的
  • 10:无意义
  • 11:除了停止模式,其他时候都是运行的

我们可以选择11来使能时钟,我们使用的是GPIO1,我们找到,GPIO1的时钟使能是通过CCM_CCGR1的27-26位控制的。

我们只需要让CCM_CCGR1中的27-26位为1就可以了,或者我们直接让所有位均为1。

GPIO复用配置

我们点亮LED使用的肯定是输出模式,控制GPIO复用模式的寄存器为“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”,我们需要将它设置为0x5。

GPIO电气属性

设置GPIO电气属性的寄存器为“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03

0 SRE:设置压摆率,当此位为0,是低压摆率;当为1时,是高压摆率。这里压摆率就是IO电平跳变的时间,电平跳变的时间越小波形越陡,说明压摆率越高,反之则压摆率越低。如果此IO用于高速通信,建议使用高压摆率。

5:3 DSE:用于设置驱动能力,共有8个选择:

7:6 SPEED:设置IO的速率

  • 00:低速 50M
  • 01/10:中速 100M
  • 11:最大速度 200M

11 ODE:设置IO禁止或者使能开漏输出,0为禁止开漏输出,1为使能开漏输出。

12 PKE:设置IO禁止或者使能上下拉/状态保持器功能,1为使能上下拉和状态保持器,0为禁止上下拉/状态保持器。

13 PUR:设置使用上下拉还是使用状态保存期,0是用状态保存期,q的使用上下拉。

15:14 PUS:设置上下拉电阻

16 HYS:用来使能迟滞比较器(不了解)

现在我们已经分析完了电气属性中每个位的功能,没有分析到的就是无用的位,我们现在开始编写汇编代码。

配置GPIO功能

配置GPIO的输入或输出的寄存器是”GPIOx_GDIR“,我们使用的GPIO1对应的地址为0x0209C004,该寄存器中的每一个位对应一个IO,0为输入,1为输出。

设置电平状态

这是电平状态的寄存器为”GPIOxDR“,我们使用的为”GPIO1DR“

汇编代码

.global _start @全局标号

_start:
      /* 使能时钟
      * 使能所有时钟
      */
     ldr r0, =0X020C4068 /* 寄存器 CCGR0 */
     ldr r1, =0XFFFFFFFF 
    str r1, [r0] 

     ldr r0, =0X020C406C /* 寄存器 CCGR1 */
     str r1, [r0]

     ldr r0, =0X020C4070 /* 寄存器 CCGR2 */
     str r1, [r0]

     ldr r0, =0X020C4074 /* 寄存器 CCGR3 */
     str r1, [r0]

     ldr r0, =0X020C4078 /* 寄存器 CCGR4 */
     str r1, [r0]

     ldr r0, =0X020C407C /* 寄存器 CCGR5 */
     str r1, [r0]

     ldr r0, =0X020C4080 /* 寄存器 CCGR6 */
     str r1, [r0]


      /* 配置GPIO
        * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器地址为0x02E0068
        * 设置  IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03为5
        */
      ldr r0, =0x02E0068
      ldr r1, =0x5
      str r1,[r0]

       /*设置电气属性
        * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03)寄存器地址为0x020E02F4
        * 0  压摆率:0
        * 5:3 驱动能力:110
        * 7:6 速率:10
        * 11 开路输出: 0
        * 12 上下拉/状态保存使能:1
        * 13 上下拉/状态保存设置:0
        * 14:15 上下拉电阻:00
        *  迟滞比较器使能:0
        */
     ldr r0, =0x020E02F4
     ldr r1, =0x10B0
     str r1, [r0]
    
     /*设置GPIO功能
       * GPIO1_GDIR寄存器地址为0x0209C004
       * 设置GPIO1_GDIR的bit3为1
       */
       ldr r0, =0x0209C004
       ldr r1, =0x8
       str r1, [r0]

       /* 开灯,设置GPIO0_IO3为0
         * GPIO1DR寄存器的地址为0x0209C000
         */
     ldr r0, =0x0209C000
     ldr r1, =0x0
     str r1, [r0]

loop:
    b loop

编译程序

将.c.s文件变为.o、

需要使用交叉编译器arm-linux-gnueabihf-gcc来编译,工作空间的文件目录下输入指令:

//arm-linux-gnueabihf-gcc -g -c 汇编文件 -o 转换后的文件名.o
arm-linux-gnueabihf-gcc -g -c led.s -o led.o

“-g”选项是产生调试信息,GND能够使用这些调试信息进行代码调试;“-c”选项是编译源文件,而不是链接;“-o”选项是指定编译产生的文件名称。

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

需要使用交叉编译器arm-linux-gnueabihf-ld来连接,将多个.o文件连接到一个指定的链接位置(地址)。所以我们在链接的时候要指定链接起始地址,起始地址就是代码运行的起始地址。

6ULL链接地址应指向RAM,因为Cortex-A没有内部flash。RAM范围为(0x900000~0x91FFFF)。或者放到外部DDR中。(正点原子阿尔法开发板的512MB)DDR的地址范围为(0x80000000~0x9FFFFFFF)。

正点原子使用文档中,使用的是0x87800000,是与Uboot统一使用,不容易记混。

我们使用命令

arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
  • -Ttext 表示链接地址
  • -o 表示指定链接生成的elf文件

我们此时工作空间就多了一个elf文件,但是我们最后烧录的是bin文件,所以还需要将elf转为bin文件。

将elf文件转为bin文件

使用命令“arm-linux-gnueabihf-objcopy

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

  • -O指定什么格式输出
  • binary 二进制格式输出
  • -S表示不要复制源文件中的重定位信息和符号信息
  • -g表示不复制源文件的调试信息

将elf文件转为汇编(反汇编)

arm-linux-gnueabihf-objdump -D led.elf > led.dis

上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前工作空间下出现一个名为 led.dis 文件。

烧录程序

烧录使用的是SD卡方式,(SD卡必须支持FAT32模式),32G一下默认为FAT32模式。

在Ubuntu下向SD卡烧写程序,烧写程序为将bin文件烧写到SD卡绝对地址上。 而且对于IMX6ULL而言,不能直接烧录bin文件,比如要在bin文件添加头部。这个部分我使用的是正点原子提供的imxdownload软件。

将imxdownload复制到工作空间中

将imxdownload复制到工作空间,并基于执行权限,这里的777是给予全部权限,然后可以看到我们的imxdownload会变成绿色。

chmod 777 imxdownload

查看SD卡位置

使用ls /dev/sd* -l查找,我们在拔出时候查看一次,插入之后再查看一次,新增的就是我们的SD卡位置。

可以看到,我的虚拟机上每次插拔,sdb会重新出现,同时伴随着sdb1。

烧写

烧写的命令是

// ./imxdownload 烧写的文件 烧写的地址
./imxdownload led.bin /dev/sdb

烧写完成后,他会显示时间和内存大小,与STM32类似。然后我们可以发现,此时我们工作空间中多了一个load.imx文件,那么load.imx就是我们要最后烧录的SD卡的文件。

插板

我们将SD卡插入到板子中,按复位键后(将拨码拨到SD卡模式),1-2秒后LED点亮。

为什么会延时:因为内部Uboot运行,首先检测从什么地方启动代码,从SD卡中读代码,SD卡头部中又有一些配置信息。然后先把我们代码放到我们的链接地址中,然后才是运行我们的代码,所以会有1-2s的延时。

恭喜你,成功称为I.MX6ULL的点灯大师!!!

在Linux中体现编译烧录的过程,岂不快哉?

如果你看到这了,那么我再讲一点吧

快速的编译烧录

我们编译的时候是在一直输命令,这样太麻烦。我们最好的方法就是创建makefile。

我们在工作空间下新建文件“Makefile”

我们的目标是led.bin,依赖是led.s。

之后我们需要执行相应的命令:

  • 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

并在最后清零工程

总体下来就是:

led.bin:led.s
    arm-linux-gnueabihf-gcc -g -c led.s -o led.o  //(前面的缩进一定要用Tab进行,否则报错)
    arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
    arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
clean:
    rm -rf *.o led.bin led.elf

使用:

在工作空间中执行make指令;清理的话就是make clean。

如果您觉得这篇文章不错,且手里较为宽裕,可以支持一下博主,一分也是缘分😊
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇