zoukankan      html  css  js  c++  java
  • 一.LED灯的点亮——从简单的汇编开始了解

    首先,我们一步步从汇编开始点亮板子上的LED灯!

    为什么要先从汇编开始呢?一般来说我们只用C写程序就行了,但是系统上电以后要对SOC的外设、DDR进行初始化(我们用的是I.MX6U,不需要这一步),设置堆栈指针(一般指向DDR),设置好C语言的环境关闭看门狗等流程,但这些功能用C是无法实现的,必须通过汇编来做。好在只需要简单几个指令就可以了。

    下面我们从开发板的LED硬件来分析下原理:

    先看下硬件原理图:

                     

    灯通过3.3V供电,经过510欧的限流电阻和控制口LED0相连,通过搜索查询,我们发现LED0节点和GPIO_3相连(应该是GPIO1_3)

    以前搞过STM32的伙伴们应该知道,要对IO进行初始化,需要下面的流程:

    1. 使能GPIO时钟
    2. 设置IO复用,将其设置为GPIO
    3. 配置GPIO的电气属性
    4. 使用GPIO,输出高低电平

    对于IMX6ULL来说,流程基本是一样的,我们一步一步来设置

    一.使能GPIO时钟:

    查询IMX6ULL的芯片手册,CCM_CCGR0-6一共7个寄存器控制了6UL上所有的外设时钟的使能(第18.6.23章 CCM Clock Gating Register 0 (CCM_CCGR0)),而gpio1对应的时钟管理是归属于CCM_CCGR1的26、27两个bit管理,要想使能这个时钟,将其按照要求设置就可以了

    设置值得要求

     简单化,只要把两个比特值都置一就行了。更简单,吧CCGR0-6都设为0xFFFFFFFF,相当于使能所有外设时钟。

     二.IO复用设置

     复用设置的管理属于IOMUX Controller管理,查询芯片手册,我们要设置的是GPIO1的IO3,要设置的是IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03(SW_MUX_CTL_PAD_GPIO1_IO03 SW MUX Control Register )

    下面有个表是对其进行说明的

     复用模式(MUX_MODE)一共有7种模式,对应3-0bit,我们是要使用GPIO功能,也就是对应0101=5。

    三.设置电气属性

    下面要对GPIO1_IO03的电气属性进行设置。可以查下目录,管理其属性的寄存器是IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03(32.6.156 SW_PAD_CTL_PAD_GPIO1_IO03 SW PAD Control Register)注意跟复用的区别,一个是PAD,一个是MUX

    这个电气属性的内容比较多

    Field Description
     

    0     ODE_0_Open_Drain_Disabled — Open Drain Disabled

    1     ODE_1_Open_Drain_Enabled — Open Drain Enabled

    31–17
    -

    This field is reserved.
    Reserved

    16
    HYS

    Hyst. Enable Field
    Select one out of next values for pad: GPIO1_IO03

    0  HYS_0_Hysteresis_Disabled — Hysteresis Disabled
    1  HYS_1_Hysteresis_Enabled — Hysteresis Enabled

    15–14
    PUS

    Pull Up / Down Config. Field
    Select one out of next values for pad: GPIO1_IO03

    00  PUS_0_100K_Ohm_Pull_Down — 100K Ohm Pull Down
    01  PUS_1_47K_Ohm_Pull_Up — 47K Ohm Pull Up
    10  PUS_2_100K_Ohm_Pull_Up — 100K Ohm Pull Up
    11  PUS_3_22K_Ohm_Pull_Up — 22K Ohm Pull Up

    13
    PUE

    Pull / Keep Select Field

    Select one out of next values for pad: GPIO1_IO03

    0  PUE_0_Keeper — Keeper
    1  PUE_1_Pull — Pull

    12
    PKE

     

    Pull / Keep Enable Field
    Select one out of next values for pad: GPIO1_IO02

     

    0  PKE_0_Pull_Keeper_Disabled — Pull/Keeper Disabled
    1  PKE_1_Pull_Keeper_Enabled — Pull/Keeper Enabled

    11
    ODE

     

    Open Drain Enable Field
    Select one out of next values for pad: GPIO1_IO02

     

    10–8

    -

     This field is reserved.
    Reserved
     7–6
    SPEED
    Speed Field
    Select one out of next values for pad: GPIO1_IO03
    00  SPEED_0_low_50MHz_ — low(50MHz)
    01  SPEED_1_medium_100MHz_ — medium(100MHz)
    10  SPEED_2_medium_100MHz_ — medium(100MHz)
    11  SPEED_3_max_200MHz_ — max(200MHz)
     5–3
    DSE

    Drive Strength Field
    Select one out of next values for pad: GPIO1_IO03

    000  DSE_0_output_driver_disabled_ — output driver disabled;
    001  R0(3.3V下为260Ω,1.8V下为150Ω,接DDR时为240Ω)
    010  DSE_2_R0_2 — R0/2
    011  DSE_3_R0_3 — R0/3
    100  DSE_4_R0_4 — R0/4
    101  DSE_5_R0_5 — R0/5
    110  DSE_6_R0_6 — R0/6
    111  DSE_7_R0_7 — R0/7

     
     2–1
    -
    This field is reserved.
    Reserved 
     

    0
    SRE

     
     

    Slew Rate Field
    Select one out of next values for pad: GPIO1_IO02

    0  SRE_0_Slow_Slew_Rate — Slow Slew Rate
    1  SRE_1_Fast_Slew_Rate — Fast Slew Rate

    也就是说寄存器IOMUSXC_SW_PAD_CTL_PAD_GPIO1_IO03是用来配置GPIO_IO03的,包括速度、驱动能力压摆率等设置,下面挨个分析下这几个参数

    • SRE(bit0):压摆率,指IO电平反转所需要的时间,时间越小波形就越抖,即压摆率高。0的时候为低压摆率,1时为高。当我们的IO做高速IO时要设置为1
    • DSE(bit5-3):当IO作为输出时的驱动能力。共8个选项,0为关闭驱动,其余对应表格查询即可
    • SPEED(bit7-6):IO用作输出时的IO速度,按需求依据表格设置
    • ODE(bit11):IO作为输出时,是否使能开路输出,0时禁止开路输出,1时使能
    • PKE(bit12):用来使能或禁止上下拉、状态保持器的功能:0时禁止上下拉/状态保持器,1时使能
    • PUE(bit13):当IO为输如的时候,用来设置IO使用上下拉还是状态保持器:1时为上下拉,0时为状态保持器,即外部电路断电后此IO口可保持以前的状态。
    • PUS(bit15-14):设置上下拉电阻阻值,按需设置
    • HYS(bit16):使能迟滞比较器,当IO作为输入功能时有效,用于设置输入接收器的施密特触发器是否使能,如果需要对输入波形进行整形的时候可以使能此位,0时禁止,1时使能

    整个功能图如图所示

    四.GPIO配置

    这里还有一个要配置是在STM32里没有的:配置GPIO,包含输入/输出,数据等等

    手册里有一章是专门讲GPIO的(Chapter28) ,查寄存器目录发现有8个寄存器是我们需要设置的

    GPIO data register(GPIOx_DR)

    GPIO数据寄存器,一共32位,对应了IO的32个点,当GPIO配置为输出到时候时,0为低电平,1为高电平。当GPIO为输出到模式时,每个位对应一个GPIO,比方GPIO1_IO00引脚接地时,GPIO.DR的bit0值为0

     GPIO direction register (GPIOx_GDIR)

    方向寄存器(GPIO direction register (GPIOx_GDIR),28.5.2)

    同样也是32位,表明32个IO点工作的方向,0为输入,1为输出

    我们需要的是将GPIO1_IO03设置为输出模式,就要将GPIO1_GDIR的第3个bit置1

    剩下的还有PSR,ICR1,ICR2,IMR,ISR,EDGE_SEL我们暂时用不到,这里就先不讲了,总之,GPIO的整体配置流程如下图所示

     

    代码编写

    这里使用汇编来实现,汇编语言的介绍我们放在另一章来讲。反正这里要用到就是读取、写入寄存器。

    就按照前面的流程,先使能GPIO时钟,这里为了简化操作,把所有Soc和GPIO1一个寄存器控制的所有外设都设为使能,也就是将CCM_CCGR1全都使能。

    CCM_CCGR1的地址为20C_4000h base + 6Ch offset = 20C_406Ch(0x020c406c)

        /*使能所有外设时钟 */
        ldr r0,=0x020c4068   @CCGR0
        ldr r1,=0xffffffff   @向CCGR0待写入的数据
        str r1,[r0]          @将r1里的数据写入r0地址的寄存器

    第二步就是设置复用,对应寄存器为IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03,地址为0x020e0068,应讲MUX_MODE设置为ALT5

    @设置复用IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 5
        ldr r0,=0x020e0068
        ldr r1,=0x5
        str r1,[r0]

     第三步是设置电气属性,设置寄存器

    IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 地址0x020E02F4,对应前面的分解说明,按照下面的要求设置
    • bit 16:0 HYS关闭
    • bit [15:14]: 00 默认下拉
    • bit [13]: 0 kepper功能
    • bit [12]: 1 pull/keeper使能
    • bit [11]: 0 关闭开路输出
    • bit [10-8]: 000 空
    • bit [7:6]: 10 速度100Mhz
    • bit [5:3]: 110 R0/6驱动能力
    • bit [2:1]: 00 空
    • bit [0]: 0 低转换率
    写下来就是00001 0000 1011 0000,也就是0x10B0,使用代码实现,就是
        ldr r0,=0x020e02f4
        ldr r1,=0x10b0
        str r1,[r0]

    第四步是将GPIO设置为输出模式,也就是将GPIO1_GDIR的第2个bit置1,换算值为0x8,GPIO1_GDIR的地址为0x209c004

        ldr r0,=0x0209c004
        ldr r1,=0x8
        str r1,[r0]

    下一步就是给GPIO的数据寄存器赋值,注意看前面的硬件原理图,我们的LED要想点亮的话控制端需要为低电平,所以直接把GPIO1的值置0就好,GPIO1_DR的地址为0x209c000

        ldr r0,=0x0209C000
        ldr r1,=0
        str r1,[r0]

    最后放个死循环,让程序跑起来就行了

    loop:
        b loop

    最后放上所有的代码

    .global _start @全局标号
    _start:
    @ 开启所有时钟CCM_CCGR0-6
    
        /*使能所有外设时钟 */
        ldr r0,=0x020c4068   @CCGR0
        ldr r1,=0xffffffff   @向CCGR0待写入的数据
        str r1,[r0]          @将r1里的数据写入r0地址的寄存器内
    
    @设置复用IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 5
        ldr r0,=0x020e0068
        ldr r1,=0x5
        str r1,[r0]
    
    @设置电气属性IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 地址0x020E02F4
    /*
        @  *bit 16:0 HYS关闭
        @  *bit [15:14]: 00 默认下拉
        @  *bit [13]: 0 kepper功能
        @  *bit [12]: 1 pull/keeper使能
        @  *bit [11]: 0 关闭开路输出
        @  *bit [10-8]: 000 空
        @  *bit [7:6]: 10 速度100Mhz
        @  *bit [5:3]: 110 R0/6驱动能力
        @  *bit [2:1]:  00  空
        @  *bit [0]: 0 低转换率
        @   00001 0000 1011 0000>0x10B0
     */
    
        ldr r0,=0x020e02f4
        ldr r1,=0x10b0
        str r1,[r0]
    
    /*设置GPIO1_IO03为输出,
    GPIO1_GDIR地址为 0x209_C004
    IO03对应第2bit,值为0x8
    */
        ldr r0,=0x0209C004
        ldr r1,=0x8
        str r1,[r0]
    
    /*设置GPIO输出高电平
    GPIO1_DR,地址为0x209_C000
    IO03对应第3bit,低电平时灯点亮,值为0
    */
    
        ldr r0,=0x0209C000
        ldr r1,=0
        str r1,[r0]
    
    loop:
        b loop
    code

    整个代码的流程就完了,因为代码已经跑过,我这里就不讲调试的过程了,下一章再仔细讲一下如何编译代码

  • 相关阅读:
    18 个 Java8 日期处理的实践,太有用了!
    IntelliJ IDEA 2019.3安装激活破解使用教程
    低收入人员如何打造自己核心竞争优势
    关于企业网络营销的实战步骤
    关于如何做好微信营销和QQ营销的心得
    百度竞价项目的一些简要说明
    ASO是什么?AppStore搜索规则是什么?
    如何选择APP推广渠道和推广技巧
    浅析Hibernate映射(二)——关系映射(3)
    浅析Hibernate映射(二)——关系映射(4)
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/15726822.html
Copyright © 2011-2022 走看看