当前位置:网站首页>IMX6ULL—Assembly LED Lights
IMX6ULL—Assembly LED Lights
2022-08-09 20:15:00 【Meishan Swordsman】
I.MX6U IO 命名
参考手册的第 32 章:
分为SNVSDomain and generic,本质上都是一样的.
“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”的是 GPIO 命名,命名形式就是“IOMUXC_SW_MUC_CTL_PAD_XX_XX
”,后面的“XX_XX
”就是 GPIO 命名,比如:GPIO1_IO01、UART1_TX_DATA、JTAG_MOD 等等.
I.MX6U IO 复用
以“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”这个 IO 为例:
You can see there is a name:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 的寄存器,寄存器地址为 0X020E005C,这个寄存器是 32 位的,But only the minimum is used 5 位,其中bit0 - bit3(MUX_MODE)就是设置 GPIO1_IO00 的复用功能的.GPIO1_IO00 一共可以复用为 9种功能 IO,分别对应 ALT0~ALT8,其中 ALT5 就是作为 GPIO1_IO00.GPIO1_IO00 还可以作为 I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID 等.这个就是 I.MX6U 的 IO 复用.
如果只想看每个 IO 能复用什么外设的话可以直接查阅《IMX6ULL 参考手册》的第 4 章“Chapter 4 External Signals and Pin Multiplexing”.If you want to write code,设置某个 IO 的复用功能的话就需要查阅第 32 章“Chapter 32: IOMUX Controller(IOMUXC)”,第 32 章详细的列出了所有 IO 对应的复用配置寄存器.
I.MX6U IO 配置
GPIO1_IO00 There are two bookmarks as follows:
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00
IOMUX_SW_MUX
_CTL_PAD_GPIO1_IO00 是用来配置GPIO1_IO00 复用功能的.
IOMUXC_SW_PAD
_CTL_PAD_GPIO1_IO00 是用来配置 GPIO1_IO00 的,包括速度设置、驱动能力设置、压摆率设置等等.
I.MX6U GPIO 配置
如上图左 下 角 的 IOMUXC 框 图 里 面 就 有 SW_MUX_CTL_PAD_* 和SW_PAD_CTL_PAD_*两种寄存器.These two registers are used for setting as mentioned earlier IO 的复用功能和 IO 属性配置.upper left part GPIO The block diagram is,当 IO 用作 GPIO 的时候需要设置的寄存器,一共有八个:DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR
.
DR 寄存器
输出:0或者1
此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应
一个 GPIO.
要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1.
当 GPIO被配置为输入模式以后,此寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO,例如,当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0.
GDIR 寄存器
设置 GPIO 为输入,就设置相应的位为 0,如果要设置为输出的话就设置为 1.比如要设置 GPIO1_IO00 为输入,那么 GPIO1.GDIR=0;
PSR 寄存器
同样的 PSR 寄存器也是一个 GPIO 对应一个位,读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值.功能和输入状态下的 DR 寄存器一样.
ICR1和ICR2寄存器
ICR1用于配置低16个GPIO,ICR2 用于配置高 16 个 GPIO.
ICR1 用于 IO0-15 的配置, ICR2 用于 IO16~31 的配置.ICR1 寄存器中一个 GPIO 用两个位,这两个位用来配置中断的触发方式,和 STM32 interrupts are similar,Configurable line selection is shown in the table.
IMR 寄存器—中断屏蔽寄存器
IMR 寄存器也是一个 GPIO 对应一个位,IMR 寄存器用来控制 GPIO 的中断禁止和使能,如果使能某个 GPIO 的中断,那么设置相应的位为 1 即可,反之,如果要禁止中断,Then set the corresponding bit to 0 即可.例如,要使能 GPIO1_IO00 的中断,那么就可以设置 GPIO1.MIR=1.
ISR寄存器—中断状态寄存器
ISR 寄存器也是 32 位寄存器,一个 GPIO 对应一个位,只要某个 GPIO 的中断发生,那么ISR 中相应的位就会被置 1.所以,可以通过读取 ISR 寄存器来判断 GPIO 中断是否发生,相当于 ISR These bits are the interrupt flag bits.After the interrupt is handled,必须清除中断标志位,清除方法就是向 ISR 中相应的位写 1,也就是写 1 清零.
EDGE_SEL 寄存器—边沿选择寄存器
EDGE_SEL 寄存器用来设置边沿中断,This register will be overwritten ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位.如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发.例如,设置 GPIO1.EDGE_SEL=1,那么就表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发.
关于 GPIO The registers are explained here,因为 GPIO is the most commonly used function,详细的讲解了 GPIO的 8 个寄存器. I.MX6U 的 IO 是需要配置和输出的、是可以设置输出高低电平,也可以读取 GPIO 对应的电平.
I.MX6U GPIO 时钟使能
CCM_CCGR0 结构体如图:
CCM_CCGR0 是个 32 位寄存器,其中每 2 位控制一个外设的时钟,比如 bit31:30 控制着GPIO2 的外设时钟,两个位就有 4 种操作方式,如表所示:
如果要打开 GPIO2 的外设时钟,那么只需要设置CCM_CCGR0 的 bit31 和 bit30 都为1即可,也就是CCM_CCGR0=3 << 30.反之,如果要关闭GPIO2 的外设时钟,那就设置 CCM_CCGR0 的 bit31和bit30都为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,设置输入/输出、是否使用中断、默认输出电平等.
Assemble the lighting example
1、使能 GPIO1 时钟
GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 These two bits control,Set both bits 11 即可.
2、设置 GPIO1_IO03 的复用功能
找到 GPIO1_IO03 multiplexed register“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为0X020E0068,Then set this register,将 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5.
3、配置 GPIO1_IO03
找到 GPIO1_IO03 的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为0X020E02F4,根据实际使用情况,Configure this register.
4、设置 GPIO
将 GPIO1_IO03 复用为了 GPIO 功能,所以需要配置 GPIO.找到 GPIO3 对应的 GPIO Group register address,在《IMX6ULL 参考手册》的 1357 页,如图所示:
实验中 GPIO1_IO03 is used as an output function,因此 GPIO1_GDIR 的 bit3 要设置为 1,表示输出.
5、控制 GPIO 的输出电平
经过前面几步,GPIO1_IO03 已经配置好了,只需要向 GPIO1_DR 寄存器的 bit3 写入 0 即可控制 GPIO1_IO03 输出低电平,打开 LED,向 bit3 写入 1 可控制 GPIO1_IO03 输出高电平,关闭 LED.
.global _start /* 全局标号 */
//A global label is defined_start,The code is from_start This label starts to execute sequentially.
/* * 描述: _start函数,程序从此函数开始执行此函数完成时钟使能、 * GPIO初始化、最终控制GPIO输出低电平来点亮LED灯. */
_start:
/* 例程代码 */
/* 1、使能所有时钟 */
//CCGR0
ldr r0, =0X020C4068 /* 使用 ldr instruction to register r0 写入 0X020C4068,也就是 r0=0X020C4068,这个是CCM_CCGR0 寄存器的地址*/
ldr r1, =0XFFFFFFFF /*使用 ldr instruction to register r1 写入 0XFFFFFFFF,也就是 r1=0XFFFFFFFF.Because all peripheral clocks are turned on,因此 CCM_CCGR0~CCM_CCGR6 of all registers 32 location must be set 1,也就是写入 0XFFFFFFFF.*/
str r1, [r0] /*使用 str 将 r1 中的值写入到 r0 to the saved address,也就是给 0X020C4068 这个地址写入 0XFFFFFFFF,相当于 CCM_CCGR0=0XFFFFFFFF,就是打开 CCM_CCGR0 All peripheral clocks controlled by the registers.*/
//开启CCGR1的时钟
ldr r0, =0X020C406C /* CCGR1 */
str r1, [r0]
//开启CCGR2的时钟
ldr r0, =0X020C4070 /* CCGR2 */
str r1, [r0]
//开启CCGR3的时钟
ldr r0, =0X020C4074 /* CCGR3 */
str r1, [r0]
//开启CCGR4的时钟
ldr r0, =0X020C4078 /* CCGR4 */
str r1, [r0]
//开启CCGR5的时钟
ldr r0, =0X020C407C /* CCGR5 */
str r1, [r0]
//开启CCGR6的时钟
ldr r0, =0X020C4080 /* CCGR6 */
str r1, [r0]
/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
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]
/* 4、设置GPIO1_IO03为输出 */
ldr r0, =0X0209C004 /*寄存器GPIO1_GDIR */
ldr r1, =0X0000008
str r1,[r0]
/* 5、打开LED0 * 设置GPIO1_IO03输出低电平 */
ldr r0, =0X0209C000 /*寄存器GPIO1_DR */
ldr r1, =0
str r1,[r0]
/* * 描述: loop死循环 */
loop:
b loop
编译命令
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
arm-linux-gnueabihf-objdump -D led.elf > led.dis
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
arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
rm -rf *.o led.bin led.elf led.dis
连接脚本文件
arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^
示例代码 10.4.2.2 imx6ul.lds Link script code
1 SECTIONS{
2 . = 0X87800000;
3 .text :
4 {
5 start.o
6 main.o
7 *(.text)
8 }
9 .rodata ALIGN(4) : {
*(.rodata*)}
10 .data ALIGN(4) : {
*(.data) }
11 __bss_start = .;
12 .bss ALIGN(4) : {
*(.bss) *(COMMON) }
13 __bss_end = .;
14 }
代码烧写
programming format:
./imxdownload <.bin file> <SD Card>
其中.bin 就是要烧写的.bin 文件,SD Card 就是要烧写的 SD 卡.
./imxdownload led.bin /dev/sdd //不能烧写到/dev/sda 或 sda1 设备里面!那是系统磁盘
现象
边栏推荐
猜你喜欢
试试使用 Vitest 进行组件测试,确实很香。
最强分布式锁工具:Redisson
What is test development and why is it so popular now?
The most complete architect knowledge map in history
An in-depth understanding of the implementation principle of Hybrid
十七、一起学习Lua 错误处理
ASP.NET Core依赖注入之旅:针对服务注册的验证
Discuz!论坛程序安装+模板配置教程
2022 全球 AI 模型周报
A carnival of art and technology, cloud XR supports Anaya 2022 Sandbox Immersive Art Season
随机推荐
那些关于DOM的常见Hook封装(二)
SimpleDateFormat线程安全问题和解决方案
mysql generates random name, mobile number, date
mysql双主备份失败?
The principle implementation of handwritten flexible.js, I finally understand the multi-terminal adaptation of the mobile terminal
动态RDLC报表(一)
动态RDLC报表(七)
Metasploit——辅助模块(Auxiliary)
低代码平台和专业开发人员——完美搭档?
win10 uwp 装机必备应用 含源代码
本机号码一键登录原理
mysql如何查看所有复合主键的表名?
进程的两种创建方式,join方法,进程间的数据隔离,队列,进程间的通信IPC机制,生产者消费者模型,守护进程,僵尸进程,孤儿进程,互斥锁
测试开发是什么,为什么现在这么吃香?
传统数据中台又贵又复杂?何不试一试永久免费的下一代数据中台
最新!2022版新员工基础安全知识教育培训PPT,企业拿去直接用
虚拟修补:您需要知道的一切
CPU状态信息us,sy,ni,id,wa,hi,si,st含义
.NET 6学习笔记(4)——解决VS2022中Nullable警告
动态RDLC报表(六)