汇编LED驱动实验(正点原子Linux第5讲笔记优化)

一、汇编LED原理分析

  1. 为什么要学习Cortex-A汇编:
  2. ①、需要用汇编初始化一些SOC外设。
  3. ②、使用汇编初始化DDR,I.MX6U不需要。
  4. ③、设置sp指针,一般指向DDR,设置好C语言运行环境。

1、·ALPHA开发板LED灯硬件原理分析:

  1. STM32 IO初始化流程:
  2. ①、使能GPIO时钟。
  3. ②、设置IO复用,将其复用为GPIO
  4. ③、配置GPIO的电气属性。
  5. ④、使用GPIO,输出高/低电平。

I.MX6ULL IO初始化:

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

汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第1张图片

.global _start @全局标号

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

    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]  

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

汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第2张图片

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

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

     汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第3张图片

 汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第4张图片

    /* 配置GPIO1_IO03的电气属性 也就是寄存器:
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器地址为0x020e02f4
     *
     * bit0:    0 低速率
     * bit5:3: 110 R0/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寄存器bit3为1,也就是设置为输出模式。

汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第5张图片汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第6张图片

    /* 设置GPIO 
     * 设置GPIO1_GDIR寄存器,设置GPIO1_GPIO03为输出
     * GPIO1_GDIR寄存器地址为0x0209c004,设置GPIO1_GDIR寄存器bit3为1,
     * 也就是设置GPIO1_IO03为输出。
     */
     ldr r0, = 0x0209c004
     ldr r1, = 0x8
     str r1, [r0]

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

 汇编LED驱动实验(正点原子Linux第5讲笔记优化)_第7张图片

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

loop:
    b loop 

三、汇编简介

汇编由一条一条指令构成,指令就涉及到汇编指令。

  • Int a,b;
  • a=b;
  • 假设a地址为0X20,b地址为0x30
  • LDR R0, =0X30
  • LDR R1, [R0]
  • LDR R0, =0X20
  • STR R1, [R0]
  • 我们在使用汇编编写驱动的时候最常用的就是LDR和STR这两个指令。

四、编写驱动

.global _start @全局标号

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

    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 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_IO03的电气属性 也就是寄存器:
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
     * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器地址为0x020e02f4
     *
     * bit0:    0 低速率
     * bit5:3: 110 R0/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寄存器,设置GPIO1_GPIO03为输出
     * GPIO1_GDIR寄存器地址为0x0209c004,设置GPIO1_GDIR寄存器bit3为1,
     * 也就是设置GPIO1_IO03为输出。
     */
     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 

五、编译程序

  • 1、编译程序
  • ①、使用arm-linux-gnueabihf-gcc将.c .s文件变为.o
  • ②、将所有的.o文件连接为elf格式的可执行文件。
  • ③、将elf文件转为bin文件。
  • ④、将elf文件转为汇编,反汇编。

链接:

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

对于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内部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.MX而言,不能直接烧写bin文件,比如先在bin文件前面添加头部。完成这个工作,需要使用正点原子提供的imxdownload软件。

Imxdownload使用方法,确定要烧写的SD卡文件,我的是/dev/sdf。

给予imxdownload可执行权限:

Chmod 777 imxdownload

烧写:

./imxdownload led.bin /dev/sdf

Imxdownlaod会向led.bin添加一个头部,生成新的load.imx文件,这个load.imx文件就是最终烧写到SD卡里面去的。、

参考资料:《i.MX 6UltraLite Applications Processor Reference Manual》;

《I.MX6U  嵌入式 x Linux  驱动开发指南 V1.5 5. .1 1》

你可能感兴趣的:(Linux,单片机,linux,stm32,c语言,c++)