首先:操作LED就要操作GPIO  alpha的芯片是NXP的IMX6ULL  其GPIO和STM32的命名有所区别

                

  可以看到IMX6ULL的GPIO以其功能进行命名,对应上图中PAD之后的部分

    即GPIO_IO00~GPIO_IO09 和JTAG_MOD等,用户按照名字就可以知道对应引脚的功能。并且IMX6ULL的GPIO也是可以复用的。

  I.MX6U 的 GPIO 一共有 5 组: GPIO1、 GPIO2、 GPIO3、 GPIO4 和 GPIO5

    其中 GPIO1 有 32 个 IO, GPIO2 有 22 个 IO, GPIO3 有 29 个 IO、 GPIO4 有 29 个 IO, GPIO5最少,只有 12 个 IO,这样一共有 124 个 GPIO  

对IO的配置


  首先要确定IO的复用功能是GPIO,看一下控制复用功能的寄存器(这里截取的是GPIO1_IO00的复用控制寄存器)

       

    显然,bit4是复用功能的“总开关”,设置为1时强制为GPIO1_IO00功能;置0时由bit3:0来决定

    bit3:0决定该IO复用为什么功能,可以看到这里ALT5就是复用为GPIO1_IO00功能,除此之外还有八种可选

  再看一下IO的功能图  

                 

  功能图中

      HYS:用来使能迟滞比较器,当 IO 作为输入功能的时候有效,用于设置输入接收器的施密特触发器是否使能。

         如果需要对输入波形进行整形的话可以使能此位。此位为 0 的时候禁止迟滞比较器,为 1 的时候使能迟滞比较器。

      PUS:用来设置上下拉电阻的,一共有四种选项可以选择,分别为100K下拉,47K上拉,100K上拉,22K上拉。

      PUE(图中未给出):当 IO 作为输入的时候,这个位用来设置 IO 使用上下拉还是状态保持器。

         当为 0 的时候使用状态保持器,当为 1 的时候使用上下拉。

         状态保持器在IO 作为输入的时候才有用,顾名思义,就是当外部电路断电以后此 IO 口可以保持住以前的状态。

      PKE:此为用来使能或者禁止上下拉/状态保持器功能,为0 时禁止上下拉/状态保持器,为 1 时使能上下拉和状态保持器。
      ODE:当 IO 作为输出的时候,此位用来禁止或者使能开路输出,此位为 0 的时候禁止开路输出,当此位为 1 的时候就使能开路输出功能。

      SPEED:当 IO 用作输出的时候,此位用来设置 IO 速度,分别为低俗50M,中速100M,中速100M,最大速度200M。

      DSE:当 IO 用作输出的时候用来设置 IO 的驱动能力,总共有 8 个可选选项

          

      SRE:设置压摆率,当此位为 0 的时候是低压摆率,当为 1的时候是高压摆率。

         这里的压摆率就是 IO 电平跳变所需要的时间,比如从 0 到 1 需要多少时间,时间越小波形就越陡,说明压摆率越高;

  对应每个IO,都有一组寄存器去控制,这是毋庸置疑的,下面是GPIO_IO00的控制寄存器

  

  

 可见 对于IO的每个功能端都有相应的寄存器位进行配置。


GPIO功能配置  

 但是我们没有看到如何设置 IO 为输入还是输出? 因为上面的配置只是针对IO的配置,对于GPIO来说,它只是IO的一个复用功能而已,所以还要对GPIO的功能进行配置。

 所以对于GPIO来说,也需要有相应的寄存器来控制,GPIO的控制框图如下:

           

    可见,配置好SW_MUX_CTL_PAD和SW_PAD_CTL_PAD两个寄存器后,还需要对GPIO进行单独配置,共有DR/GDIR/PSR/ICR1/ICR2/EDGE_SEL/IMR/ISR八个寄存器

    

     I.MX6U 一共有GPIO1~GPIO5 共五组 GPIO,每组 GPIO 都有这 8 个寄存器。


DR寄存器:数据寄存器(data register)

    

  此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应一个 GPIO。

  当 GPIO 被配置为输出功能以后,向指定的位写入数据那么相应的 IO 就会输出相应的高低电平,比如要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1。

  当 GPIO 被配置为输入模式以后,此寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO,例如,当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0。

      

  这里注意:如果GDIR[n]设置为输入,但该IO复用功能不是GPIO,那么读DR[n]始终是0值,所以读之前请确认IO是否复用为GPIO。


GDIR寄存器:方向寄存器(GPIO direction register)

  

  很简单,每一个位对应一个GPIO,对应位为0则该位为输入模式,反之为输出模式。


PSR寄存器:GPIO状态寄存器(pad status register)

  这个寄存器是只读的,读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值。功能和输入状态下的 DR 寄存器一样。

  


ICR寄存器:中断配置寄存器(interrupt configuration register)

  分为ICR1和ICR2两个寄存器,分别配置低16位和高16位GPIO,即每个GPIO占两位。

  

    通过每个GPIO对应的两位设置可以配置低电平、高电平、上升沿、下降沿四种模式。


IMR寄存器:中断屏蔽寄存器(interrupt mask register)

  每个GPIO对应一位,0为屏蔽中断,1为使能中断

  (个人认为这里的屏蔽翻译不恰当,因为下面UNMASKED和MASKED的功能和使用中屏蔽的意思好像是相反的呢?)

   


ISR寄存器:中断状态寄存器(interrupt status register)

  当中断发生时,相应中短线对应的位被置1,用来在特定中断组中查询是哪条中短线发生了中断。

  在每次处理中断完成后必须手动清零,清除的方法是向要清除的位写1。

  


EDGE_SEL寄存器:边沿选择寄存器(edge select register)

   EDGE_SEL 寄存器用来设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位。

   如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发。

   例如,我们设置 GPIO1.EDGE_SEL=1,那么就表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发。

   因为ICR中没有双边沿的设置选项。

  



GPIO时钟配置

  配置完相应GPIO的功能还不能使GPIO工作起来,还要对GPIO的时钟进行使能,I.MX6U 的系统时钟参考《I.MX6UL 参考手册》的第 18 章“Chapter 18: Clock Controller Module(CCM)”

    先不研究 I.MX6U 的时钟系统,只看一下 CCM 里面的外设时钟使能寄存器。

    CMM 有 CCM_CCGR0~CCM_CCGR6 这 7 个寄存器,这 7 个寄存器控制着 I.MX6U 的所有外设时钟开关


CCM_CCGR0 寄存器:CCM时钟门控寄存器(CCM Clock Gating Register 1)

  CCM_CCGR0 是个 32 为寄存器,其中每 2 位控制一个外设的时钟 ,例如这里的bit31:30控制GPIO2的时钟

      

  其设置方法为:对于GPIO来说,开启时钟即两位都置1,关闭则两位都置0。

    



 总结起来,要将 I.MX6U 的 IO 作为 GPIO 使用,我们需要以下几步:

      ①、使能 GPIO 对应的时钟。
      ②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能。
      ③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等等。
      ④、第②步已经将 IO 复用为了 GPIO 功能,所以需要配置 GPIO,设置输入/输出、是否使用中断、默认输出电平等。


硬件分析

    

  显然,低电平点灯,高电平灭灯。



 点灯程序编写

    对 GPIO1_IO03 做如下设置:

    1、使能 GPIO1 时钟
        GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制,将这两个位都设置为11即可。本教程所有例程已经将 I.MX6U 的所有外设时钟都已经打开了,因此这一步可以不用做。
    2、设置 GPIO1_IO03 的复用功能
        找到 GPIO1_IO03 的复用寄存器“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为0X020E0068,然后设置此寄存器,将 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5。
    3、配置 GPIO1_IO03
        找到 GPIO1_IO03 的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为0X020E02F4,根据实际使用情况,配置此寄存器。

    4、设置 GPIO
        我们已经将 GPIO1_IO03 复用为了 GPIO 功能,所以我们需要配置 GPIO。找到 GPIO3 对应的 GPIO 组寄存器地址

        

        本实验中 GPIO1_IO03 是作为输出功能的,因此 GPIO1_GDIR 的 bit3 要设置为 1,表示输出。
    5、控制 GPIO 的输出电平
        经过前面几步, GPIO1_IO03 已经配置好了,只需要向 GPIO1_DR 寄存器的 bit3 写入 0 即可控制 GPIO1_IO03 输出低电平,打开 LED,向 bit3 写入 1 可控制 GPIO1_IO03 输出高电平,关闭 LED。


    具体程序

 1 /*
2 * @Author: qjx
3 * @Date: 2020-05-02 14:16:50
4 * @Last Modified by: qjx
5 * @Last Modified time: 2020-05-02 14:48:38
6 * 汇编点灯程序
7 */
8
9 /*全局标号 */
10 .global _start
11
12 /*
13 * _start函数,程序从这里开始
14 * 分别完成: 1、时钟使能
15 2、IO复用
16 3、GPIO配置
17 4、控制GPIO.DR寄存器点灯
18 */
19
20 _start:
21 /*第一步:使能所有时钟 */
22
23 ldr r0,=0X020C4068 @CCGR0地址
24 ldr r1,=0XFFFFFFFF @设置的值(全1)
25
26 str r1,[r0] @把r1存到r0指向的地址中
27
28 ldr r0,=0X020C406C @CCGR1地址
29 str r1,[r0] @把r1存到r0指向的地址中
30
31 ldr r0,=0X020C4070 @CCGR2地址
32 str r1,[r0] @把r1存到r0指向的地址中
33
34 ldr r0,=0X020C4074 @CCGR3地址
35 str r1,[r0] @把r1存到r0指向的地址中
36
37 ldr r0,=0X020C4078 @CCGR4地址
38 str r1,[r0] @把r1存到r0指向的地址中
39
40 ldr r0,=0X020C407C @CCGR5地址
41 str r1,[r0] @把r1存到r0指向的地址中
42
43 ldr r0,=0X020C4080 @CCGR6地址
44 str r1,[r0] @把r1存到r0指向的地址中
45
46 /*第二步、设置GPIO1_IO03复用为GPIO_IO03 */
47 ldr r0,=0X020E0068 @SW_MUX_CTL_PAD_GPIO1_IO03的地址
48 ldr r1,=0X00000005 @设置低4位为0101
49 str r1,[r0] @把r1存到r0指向的地址中
50
51 /*第三步、配置GPIO */
52 /*
53 *bit 16:0 HYS 关闭
54 *bit [15:14]: 00 默认下拉
55 *bit [13]: 0 kepper 功能
56 *bit [12]: 1 pull/keeper 使能
57 *bit [11]: 0 关闭开路输出
58 *bit [7:6]: 10 速度 100Mhz
59 *bit [5:3]: 110 R0/6 驱动能力
60 *bit [0]: 0 低转换率
61 */
62 ldr r0,=0X020E02F4 @SW_PAD_CTL_PAD_GPIO1_IO03的地址
63 ldr r1,=0X000010B0 @设置对应属性
64 str r1,[r0] @把r1存到r0指向的地址中
65
66 /*第四步、设置GPIO_IO03为输出 */
67 ldr r0,=0X0209C004 @GPIO1_GDIR的地址
68 ldr r1,=0X00000008 @设置bit3为1
69 str r1,[r0] @把r1存到r0指向的地址中
70
71 /*第五步、打开LED 设置输出低电平 */
72 ldr r0,=0X0209C000 @GPIO1_DR的地址
73 ldr r1,=0X00000000 @全为0
74 str r1,[r0] @把r1存到r0指向的地址中
75
76 loop:
77 b loop


编译代码

  1、 arm-linux-gnueabihf-gcc 编译文件

1 arm-linux-gnueabihf-gcc -g -c led.s -o led.o

    上述命令就是将 led.s 编译为 led.o,其中“-g”选项是产生调试信息, GDB 能够使用这些调试信息进行代码调试。

    “-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为 led.o。执行上述命令以后就会编译生成一个 led.o 文件
  2、 arm-linux-gnueabihf-ld 链接文件

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

     上述命令中-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里我们命名为 led.elf。上述命令执行完以后就会在工程目录下多一个 led.elf 文件
     注:这里的链接地址可以是0X80000000  为了和后面Uboot的地址统一 不容易记混 这里取了0X87800000
  3、 arm-linux-gnueabihf-objcopy 格式转换

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

    .elf不是最终烧写到SD的文件,需要转换为.bin文件

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


    到这里就已经具备烧录条件了,alpha需要SD卡启动,要把imxdownload拷贝到工程文件夹下(只能在linux下运行)

    给予它可执行权限

1 chmod 777 imxdownload

    确定要烧写的SD卡名称后进行烧录

1 ./imxdownload led.bin /dev/(对应的sd卡名称)

    然后把SD卡插入卡槽,调整拨码开关至 1 7开

    上电可以看到LED微闪一下,稍后正常点亮,说明烧录成功。


  续上:

  4、 arm-linux-gnueabihf-objdump 反汇编
    大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,比如如下命令:

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

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



将上面的步骤做成Makefile

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



                                                  2020-05-02 15:38:07

5.汇编实现裸机LED的更多相关文章

  1. Tiny4412汇编流水灯代码,Tiny4412裸机LED操作【转】

    本转载自:http://www.techbulo.com/1313.html Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 2014年10月20日 ⁄ 裸机程序 ⁄ 共 4171字 ...

  2. Tiny4412汇编流水灯代码,Tiny4412裸机LED操作[1]

    从今天开始就正式进入到tiny4412的开发学习中了,今天主要看了一下Tiny4412的启动流程及存储器映射及Exynos4412数据手册,用汇编写了一个跑马灯程序(后续会有C语言版本的出来),先说一 ...

  3. 从点亮一个LED开始,Cortex-A9裸机程序设计

    电路原理图: 如何点亮一个LED? 通过对原理图进行分析,我们能够发现给三极管的基极加上一个高点平时,三级管be结导通构成通路,此时二极管就点亮了.若要将LED熄灭只需取消高电平输出. 如何使三级管基 ...

  4. Tiny4412之C语言实现流水灯,Tiny4412裸机程序[3]

    在前边我们使用汇编完成了一个流水灯实验: Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 ---- - -- -- -- - -- -- 修改: # ${MKBL2} ${SOURCE ...

  5. c语言环境初始化&c语言和汇编混合编程

    bootloader通常会分为两个阶段:第一阶段采用汇编语言来编写,主要是一些核心的初始化工作(内存,时钟的初始化),第二阶段使用C语言来编写,主要是它会完成一些板载硬件的初始化(串口,网口)然后其启 ...

  6. Exynos4412 中断处理流程详解

    Linux 中,当外设触发中断后,大体处理流程如下: a -- 具体CPU architecture相关的模块会进行现场保护,然后调用machine driver对应的中断处理handler; b - ...

  7. arm:jlink调试和直接烧写运行的不同 [mdk s3c2440]

    1.对全局变量的初始化. 2.还没发现的事例. /*************************************************/ 先上连接文件sct LR_ROM1 0x3000 ...

  8. Part10-C语言环境初始化-一跃进入C大门lesson3

    1.跳转到c代码 因为内存中的代码来自于垫脚石SRAM,他们是相同的. 采用绝对跳转方式来完成. 因为我们是从汇编代码跳转到c语言的程序,所以我们要提前准备一个main.c文件. 修改makefile ...

  9. 基于 Keil MDK 移植 RT-Thread Nano

    后文rtt代表RT-Thread 在官网公众号中,看到rtt发布了rtt nano,这个就很轻量级的rtos内核,把多余的驱动都裁剪了,因此移植工作量小,可以哪来学习一番,体验rtt之美 rtt现在也 ...

随机推荐

  1. Python学习随笔:使用xlwings读取和操作Execl文件的数字需要注意的问题

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在使用xlwings读取Excel文件中的数据时,所有的数字不论是整数.浮点数还是文本存放的数字,在 ...

  2. 开发实践丨用小熊派STM32开发板模拟自动售货机

    摘要:本文内容是讲述用小熊派开发板模拟自动售货机,基于论坛提供的工程代码,通过云端开发和设备终端开发,实现终端数据在的华为云平台显示. 本文内容是讲述用小熊派开发板模拟自动售货机,基于论坛提供的工程代 ...

  3. C#软件性能优化

    C#软件性能优化 1.    性能 衡量一个软件系统性能的常见指标有:响应时间.负载.资源使用率.并发数.在软件中有具体的提高性能需求时,我们需分析该系统性能的影响由哪些因素组成,再针对各部分进行性能 ...

  4. 题解 P5401 [CTS2019]珍珠

    蒟蒻语 这题太玄学了,蒟蒻写篇题解来让之后复习 = = 蒟蒻解 假设第 \(i\) 个颜色有 \(cnt_i\) 个珍珠. \(\sum\limits_{i=1}^{n} \left\lfloor\f ...

  5. Android开源项目-转载

    一.视频播放 https://github.com/lipangit/JieCaoVideoPlayer 二.图片选择 https://github.com/pengjianbo/GalleryFin ...

  6. Kubernetes K8S之鉴权RBAC详解

    Kubernetes K8S之鉴权概述与RBAC详解 K8S认证与授权 认证「Authentication」 认证有如下几种方式: 1.HTTP Token认证:通过一个Token来识别合法用户. H ...

  7. Greenplum 性能优化之路 --(一)分区表

    一.什么是分区表 分区表就是将一个大表在物理上分割成若干小表,并且整个过程对用户是透明的,也就是用户的所有操作仍然是作用在大表上,不需要关心数据实际上落在哪张小表里面.Greenplum 中分区表的原 ...

  8. 【Unity】Unity中AR Foundation的使用

    前段时间通过Unity 3d打包测试对比ARCore与ARKit环境探针的效果的过程中,在Google AR Core官网下载到了ARCore for Unity SDK,但是在苹果官网却没有找到AR ...

  9. php代码审计整理

    目录 变量覆盖 1x01.extract 变量覆盖 定义和用法 语法 漏洞产生:使用了默认设置 攻击方法:制造变量名冲突,对于需要相等的值可以同时置空 修复:设定一个冲突时的处理规则 例题: 1x02 ...

  10. 关于easyii 无法退出登录的情况

    问题描述:easyii 后台原先自己就写好了退出登录,如下图所示.点击了退出登录后,页面也会自动跳转到登录的页面.但是问题是,在浏览器点击返回的时候,还是依旧能进入到后台中,退出登录根本就没有起到作用 ...