• 嵌入式Linux裸机开发(一)基础介绍及汇编LED驱动


    系列文章目录



    前言

    现在开始正式在开发板上进行开发,仍然看的是正点原子的资料


    IMX6ULL介绍

    主要资料

    使用的是Cortex-A7
    在这里插入图片描述
    点击芯片名字打开介绍,主要参考的手册是:
    在这里插入图片描述
    以及数据手册
    在这里插入图片描述

    IO表现形式

    对于一般的STM32来说,IO的表现形式为:
    在这里插入图片描述
    管教名为PA1,管脚的功能在倒数第二列

    对于IMX6ULL,IO形式在参考手册里面,且没有上面的表格:目录列表即管教名:SNVS_TAMPER2这样格式的,是对寄存器介绍的。
    在这里插入图片描述
    下图的这两种,有MUX的表示本节介绍的是复用功能
    在这里插入图片描述
    配置其电气模式:就是速度、上下拉类似stm32那些
    在这里插入图片描述


    汇编LED驱动

    Cortex-A汇编的功能:

    • 初始化SOC外设
    • 初始化DDR(一般内部ROM存放了启动代码,读取DDR配置信息,完成DDR初始化)
    • 设置SP指针,一般指向DDR,设置好C语言环境

    原理图

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    初始化流程

    参考STM32的初始化过程:
    在这里插入图片描述

    • 使能GPIO时钟
    • 设置IO复用,复用为GPIO
    • 配置电气属性
    • 使用

    时钟设置

    对IMX6ULL来说:CCM为其时钟控制
    在这里插入图片描述
    打开发现CCGR0-6,控制了其所有的外设时钟
    在这里插入图片描述
    有几种模式,但先直接初始化为11,所有模式下都开启,且CG0-CG15都这样,即0xfffffff
    在这里插入图片描述
    这里有地址:0x20C4068
    在这里插入图片描述

    IO复用设置

    在这里插入图片描述

    需要设置为0101,即复用为GPIO模式
    SION寄存器,设置为默认0就行

    电气属性设置


    SRE(bit0): 对应图 8.1.4.2 中的 SRE,设置压摆率,当此位为 0 的时候是低压摆率,当为 1的时候是高压摆率。这里的压摆率就是 IO 电平跳变所需要的时间(高速通信就用高压摆率),要过EMC就用低压摆率。

    DSE(bit5:3):对应图 8.1.4.2 中的 DSE,当 IO 用作输出的时候用来设置 IO 的驱动能力,111驱动能力最强。
    在这里插入图片描述
    SPEED(bit7:6): 对应图 8.1.4.2 中的 SPEED,当 IO 用作输出的时候,此位用来设置 IO 速度
    在这里插入图片描述
    PUE(bit13):当 IO 作为输入的时候,为 0 的时候使用状态保持器,当为 1 的时候使用上下拉。状态保持器在当外部电路断电以后此 IO 口可以保持住以前的状态。

    PKE(bit12): 此位为0 时禁止上下拉/状态保持器,为 1 时使能上下拉和状态保持器。

    ODE(bit11):当 IO 作为输出的时候,此位为 0 的时候禁止开路输出, 当此位为 1 的时候就使能开路输出功能。

    PUS(bit15:14): 用来设置上下拉电阻的
    在这里插入图片描述
    HYS(bit16):使能迟滞比较器,当 IO 作为输入功能的时候有效,用于设置输入接收器的施密特触发器是否使能。如果需要对输入波形进行整形的话可以使能此位。此位为 0 的时候禁止迟滞比较器,为 1 的时候使能迟滞比较器。

    使用GPIO

    在这里插入图片描述

    • DR:读写数据

    • GDIR:IO是输入还是输出

    • PSR:功能和输入状态下的DR寄存器一样,读取IO状态

    • ICR1、ICR2:中断控制寄存器,ICR1配置IO0-15,ICR2配置IO16-31
      在这里插入图片描述
      要设置 GPIO1_IO15为上升沿触发中断,那么 GPIO1.ICR1=2<<30

    • IMR:中断屏蔽寄存器,使能某个 GPIO 的中断,那么设置相应的位为 1 即可,反之,如果要禁止中断,那么就设置相应的位为 0,使能 GPIO1_IO00 的中断,那么就可以设置 GPIO1.MIR=1

    • ISR:中断状态寄存器,32 位寄存器,只要某个 GPIO 的中断发生,那么ISR 中相应的位就会被置 1

    • EDGE_SEL:边沿选择寄存器,设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位。如果相应的位被置 1,那么就相当与设置了对应的 GPIO 双边沿触发。

    各个地址在这里:
    在这里插入图片描述
    以GDIR为例子:每一位代表一个IO,IO3为1即0x8
    在这里插入图片描述

    编写驱动

    .global _start   //全局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]
    
        // 设置 GPIO1_IO03 复用为 GPIO
        ldr r0, =0X020E0068 /* 将寄存器 SW_MUX_GPIO1_IO03_BASE 加载到 r0 中 */
        ldr r1, =0X5 /* 设置寄存器 SW_MUX_GPIO1_IO03_BASE 的 MUX_MODE 为 5 */
        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]
    
        //设置为输出模式
        ldr r0, =0X0209C004 /*寄存器 GPIO1_GDIR */ 
        ldr r1, =0X0000008
        str r1,[r0]
    
        //输出低电平
        ldr r0, =0X0209C000 /*寄存器 GPIO1_DR */
        ldr r1, =0
        str r1,[r0]
    
        //loop循环
    loop:
        b loop
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    编译程序

    编译.o文件

    在这里插入图片描述

    arm-linux-gnueabihf-gcc -g -c leds.s -o leds.o
    
    • 1

    用交叉编译器进行编译,“-g”选项是产生调试信息, GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为 led.o。

    地址链接.elf

    在STM32中,keil会链接存储的起始地址和运行地址0x80000000
    我们烧写到SD卡中,上电以后 I.MX6U 的内部 boot rom 程序会将可执行文件拷贝到链接地址处,这个链接地址可以在 I.MX6U 的内部 128KB RAM 中(0X900000~0X91FFFF),也可以在外部的 DDR 中。

    拷贝到DDR中:
    链接起始地址为 0X87800000。 I.MX6U-ALPHA 开发板的 DDR 容量有两种: 512MB 和256MB,起始地址都为 0X80000000,只不过 512MB 的终止地址为 0X9FFFFFFF,而 256MB 容量的终止地址为 0X8FFFFFFF。之所以选择 0X87800000 这个地址是因为后面要讲的 Uboot 其链接地址就是 0X87800000,这样我们统一使用 0X87800000 这个链接地址,不容易记混。

    arm-linux-gnueabihf-ld -Ttext 0X87800000 leds.o -o leds.elf
    
    • 1

    在这里插入图片描述
    最后还需要格式转换到bin文件:

    arm-linux-gnueabihf-objcopy -O binary -S -g leds.elf leds.bin
    
    • 1

    格式转换.bin

    arm-linux-gnueabihf-objcopy -O binary -S -g leds.elf leds.bin
    
    • 1

    “-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。
    在这里插入图片描述

    反汇编(其他)

    反汇编:多数是用 C 语言写的,有时候查看其汇编代码来调试,一般可以将 elf 文件反汇编

    arm-linux-gnueabihf-objdump -D leds.elf > leds.dis
    
    • 1

    “-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一个名为 led.dis 文件
    在这里插入图片描述

    综合成Makefile完成一步编译

    创建Makefile文件:

    leds.bin:leds.s
    	arm-linux-gnueabihf-gcc -g -c leds.s -o leds.o
    	arm-linux-gnueabihf-ld -Ttext 0X87800000 leds.o -o leds.elf
    	arm-linux-gnueabihf-objcopy -O binary -S -g leds.elf leds.bin
    	arm-linux-gnueabihf-objdump -D leds.elf > leds.dis
    clean:
    	rm -rf *.o leds.bin leds.elf leds.dis
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    烧录程序

    imxdownload

    I.MX6U 支持从外置的 NOR Flash、 NAND Flash、 SD/EMMC、 SPI NOR Flash和 QSPI Flash 这些存储介质中启动,所以我们可以将代码烧写到这些存储介质中中。在这些存储介质中,除了 SD 卡以外,其他的一般都是焊接到了板子上的,我们没法直接烧写。

    将 imxdownload 拷贝到工程根目录下,也就是和 leds.bin 处于同一个文件夹下,给予 imxdownload 可执行权限,给予 imxdownload 可执行权限以后其名字变成了绿色的,如果没有可执行权限的话其名字颜色是白色的。

    chmod 777 imxdownload
    
    • 1

    在这里插入图片描述

    准备SD卡

    ls /dev/sd*
    
    • 1

    在这里插入图片描述
    查看可知该SD卡挂载/dev/sdb、/dev/sdb1,/dev/sdd 是我的 SD 卡, /dev/sdd1 是 SD 卡的第一个分区

    向SD卡烧写程序

    ./imxdownload <.bin file> <SD Card>
    
    • 1

    在这里插入图片描述
    注意如果出现MB/s的烧写速度,肯定烧写失败,需要重启Ubuntu,这里我下载错了,应该是/dev/sdb

    烧写完成以后会在当前工程目录下生成一个 load.imx 的文件

    之后,设置为SD卡启动,按下复位键
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    Java面试题之synchronized平台级锁和Lock实现的锁区别
    MATLAB位运算
    利用对数器验证算法代码程序
    Qt5开发及实例V2.0-第二十一章-Qt.Quick Controls开发基础
    【数据结构入门_数组】 Leetcode 121. 买卖股票的最佳时机
    无人驾驶汽车的相关技术,无人驾驶相关技术知识
    佳易王会员管理系统软件如何下载,基本功能有哪些
    Java源代码是如何编译,加载到内存中的?
    基于微信平台的牙科就诊信息管理系统的设计与实现 毕业设计-附源码211157
    介绍一款数据准实时复制(CDC)中间件 `Debezium`
  • 原文地址:https://blog.csdn.net/zerokingwang/article/details/133523232