stm32

一、GCC

1、gcc 命令

gcc [选项] [文件名字]

主要选项如下:

-c:只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。

-o:<输出文件名>用来指定编译结束以后的输出文件名,如果不使用这个选项的话 GCC 默 认编译出来的可执行文件名字为 a.out。

-g:添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编 译的时候生成调试所需的符号信息。

-O:对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进 行优化,这样产生的可执行文件执行效率就高。

-O2:比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。

二、Cortex-A7 MPCore 架构

Cortex-A7 MPcore 处理器支持 1~4 核,通常是和 Cortex-A15 组成 big.LITTLE 架构的, Cortex-A15 作为大核负责高性能运算,比如玩游戏啥的,Cortex-A7 负责普通应用,因为 CortexA7 省电.

big.LITTLE 处理的设计旨在为适当的作业分配恰当的处理器。Cortex-A78 [1]核心是已开发的性能最高的 ARM 核心,而 Cortex-A55 [1] 核心是已开发的中端解决方案的最高效率动态的 ARM 核心。可以利用 Cortex-A78 [1]核心的性能来承担繁重的工作负载,而 Cortex-A55 [1] 可以最有效地处理智能手机的大部分工作负载。这些操作包括操作系统活动、用户界面和其他持续运行、始终连接的任务。

Cortex-A7MPCore 使用 ARMv7-A 架构:

①、SIMDv2 扩展整形和浮点向量操作

②、提供了与 ARM VFPv4 体系结构兼容的高性能的单双精度浮点指令,支持全功能的 IEEE754。

③、支持大物理扩展(LPAE),最高可以访问 40 位存储地址,也就是最高可以支持 1TB 的 内存。

④、支持硬件虚拟化。

⑥、支持 Generic Interrupt Controller(GIC)V2.0。

⑦、支持 NEON,可以加速多媒体和信号处理算法。

1、Cortex-A 处理器运行模型

以前的 ARM 处理器有 7 中运行模型:User、FIQ、IRQ、Supervisor(SVC)、Abort、Undef 和 System,其中 User 是非特权模式,其余 6 中都是特权模式。但新的 Cortex-A 架构加入了 TrustZone 安全扩展,所以就新加了一种运行模式:Monitor,新的处理器架构还支持虚拟化扩 展,因此又加入了另一个运行模式:Hyp,所以 Cortex-A7 处理器有 9 种处理模式

stm32_第1张图片

除了 User(USR)用户模式以外,其它 8 种运行模式都是特权模式。这几个 运行模式可以通过软件进行任意切换,也可以通过中断或者异常来进行切换。大多数的程序都 运行在用户模式,用户模式下是不能访问系统所有资源的,有些资源是受限的,要想访问这些 受限的资源就必须进行模式切换。但是用户模式是不能直接进行切换的,用户模式下需要借助 异常来完成模式切换,当要切换模式的时候,应用程序可以产生异常,在异常的处理过程中完 成处理器模式切换。

2、寄存器

ARM 架构提供了 16 个 32 位的通用寄存器(R0~R15)供软件使用,前 15 个(R0~R14)可以用 作通用的数据存储,R15 是程序计数器 PC,用来保存将要执行的指令。ARM 还提供了一个当 前程序状态寄存器 CPSR 和一个备份程序状态寄存器 SPSR,SPSR 寄存器就是 CPSR 寄存器的 备份。

stm32_第2张图片

Cortex-A7 有 9 种运行模式,每一种运行模式都有一组与之对应的寄存 器组。每一种模式可见的寄存器包括 15 个通用寄存器(R0~R14)、一两个程序状态寄存器和一个 程序计数器 PC。在这些寄存器中,有些是所有模式所共用的同一个物理寄存器,有一些是各模 式自己所独立拥有的。

stm32_第3张图片

,CortexA 内核寄存器组成如下:

①、34 个通用寄存器,包括 R15 程序计数器(PC),这些寄存器都是 32 位的。

②、8 个状态寄存器,包括 CPSR 和 SPSR。

③、Hyp 模式下独有一个 ELR_Hyp 寄存器。

2.1、通用寄存器

R0~R15 就是通用寄存器,通用寄存器可以分为以下三类:

①、未备份寄存器,即 R0~R7。 ②、备份寄存器,即 R8~R14。 ③、程序计数器 PC,即 R15。

2.1.1 未备份寄存器

未备份寄存器指的是 R0~R7 这 8 个寄存器,因为在所有的处理器模式下这 8 个寄存器都是 同一个物理寄存器,在不同的模式下,这 8 个寄存器中的数据就会被破坏。所以这 8 个寄存器 并没有被用作特殊用途。

2.1.2 备份寄存器

备份寄存器中的 R8~R12 这 5 个寄存器有两种物理寄存器,在快速中断模式下(FIQ)它们对 应着 Rx_irq(x=8~12)物理寄存器,其他模式下对应着 Rx(8~12)物理寄存器。FIQ 是快速中断模 式,看名字就是知道这个中断模式要求快速执行! FIQ 模式下中断处理程序可以使用 R8~R12 寄存器,因为 FIQ 模式下的 R8~R12 是独立的,因此中断处理程序可以不用执行保存和恢复中 断现场的指令,从而加速中断的执行过程。

备份寄存器 R13 一共有 8 个物理寄存器,其中一个是用户模式(User)和系统模式(Sys)共用 的,剩下的 7 个分别对应 7 种不同的模式。R13 也叫做 SP,用来做为栈指针。基本上每种模式 都有一个自己的 R13 物理寄存器,应用程序会初始化 R13,使其指向该模式专用的栈地址,这 就是常说的初始化 SP 指针。

备份寄存器 R14 一共有 7 个物理寄存器,其中一个是用户模式(User)、系统模式(Sys)和超 级监视模式(Hyp)所共有的,剩下的 6 个分别对应 6 种不同的模式。R14 也称为连接寄存器(LR), LR 寄存器在 ARM 中主要用作如下两种用途:

①、每种处理器模式使用 R14(LR)来存放当前子程序的返回地址,如果使用 BL 或者 BLX 来调用子函数的话,R14(LR)被设置成该子函数的返回地址,在子函数中,将 R14(LR)中的值赋 给 R15(PC)即可完成子函数返回,比如在子程序中可以使用如下代码:

stm32_第4张图片

②、当异常发生以后,该异常模式对应的 R14 寄存器被设置成该异常模式将要返回的地址, R14 也可以当作普通寄存器使用。

2.1.3 程序计数器 R15

程序计数器 R15 也叫做 PC,R15 保存着当前执行的指令地址值加 8 个字节,这是因为 ARM 的流水线机制导致的。ARM 处理器 3 级流水线:取指->译码->执行,这三级流水线循环执行, 比如当前正在执行第一条指令的同时也对第二条指令进行译码,第三条指令也同时被取出存放 在 R15(PC)中。我们喜欢以当前正在执行的指令作为参考点,也就是以第一条指令为参考点, 那么 R15(PC)中存放的就是第三条指令,换句话说就是 R15(PC)总是指向当前正在执行的指令 地址再加上 2 条指令的地址。对于 32 位的 ARM 处理器,每条指令是 4 个字节,所以: R15 (PC)值 = 当前执行的程序位置 + 8 个字节。

2.2 程序状态寄存器

所有的处理器模式都共用一个 CPSR 物理寄存器,因此 CPSR 可以在任何模式下被访问。 CPSR 是当前程序状态寄存器,该寄存器包含了条件标志位、中断禁止位、当前处理器模式标志 等一些状态位以及一些控制位。所有的处理器模式都共用一个 CPSR 必然会导致冲突,为此, 除了 User 和 Sys 这两个模式以外,其他 7 个模式每个都配备了一个专用的物理状态寄存器,叫 做 SPSR(备份程序状态寄存器),当特定的异常中断发生时,SPSR 寄存器用来保存当前程序状 态寄存器(CPSR)的值,当异常退出以后可以用 SPSR 中保存的值来恢复 CPSR。

因为 User 和 Sys 这两个模式不是异常模式,所以并没有配备 SPSR,因此不能在 User 和 Sys 模式下访问 SPSR,会导致不可预知的结果。由于 SPSR 是 CPSR 的备份,因此 SPSR 和 CPSR 的寄存器结构相同,

stm32_第5张图片

stm32_第6张图片

三、ARM 汇编基础

Cortex-A 芯片一上电 SP 指针还没初始化,C 环境还没准备 好,所以肯定不能运行 C 代码,必须先用汇编语言设置好 C 环境,比如初始化 DDR、设置 SP 指针等等,当汇编把 C 环境设置好了以后才可以运行 C 代码。所以 Cortex-A 一开始肯定是汇 编代码,其实 STM32 也一样的,一开始也是汇编,以 STM32F103 为例,启动文件 startup_stm32f10x_hd.s 就是汇编文件。

对于 Cortex-A 芯片来讲,大部分芯片在上电以后 C 语言环境还没准备好,所以第一行程序 肯定是汇编的,至于要写多少汇编程序,那就看你能在哪一步把 C 语言环境准备好。所谓的 C 语言环境就是保证 C 语言能够正常运行。C 语言中的函数调用涉及到出栈入栈,出栈入栈就要 对堆栈进行操作,所谓的堆栈其实就是一段内存,这段内存比较特殊,由 SP 指针访问,SP 指 针指向栈顶。芯片一上电 SP 指针还没有初始化,所以 C 语言没法运行,对于有些芯片还需要 初始化 DDR,因为芯片本身没有 RAM,或者内部 RAM 不开放给用户使用,用户代码需要在 DDR 中运行,因此一开始要用汇编来初始化 DDR 控制器。

1、GNU汇编语法

我们要编写的是 ARM 汇编,编译使用的 GCC 交叉编译器,所以我们的汇编代码要符合 GNU 语法。

GNU 汇编语法适用于所有的架构,并不是 ARM 独享的,GNU 汇编由一系列的语句组成, 每行一条语句,每条语句有三个可选部分,如下:

label:instruction @ comment

label 即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到 指令的地址,标号也可以用来表示数据地址。注意 label 后面的“:”,任何以“:”结尾的标识 符都会被识别为一个标号。 instruction 即指令,也就是汇编指令或伪指令。 @符号,表示后面的是注释,就跟 C 语言里面的“/”和“/”一样,其实在 GNU 汇编文 件中我们也可以使用“/”和“/”来注释。 comment 就是注释内容。

比如如下代码:

stm32_第7张图片

上面代码中“add:”就是标号,“MOVS R0,#0X12”就是指令,最后的“@设置 R0=0X12”就是 注释。

ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用 小写,但是不能大小写混用。

用户可以使用.section 伪操作来定义一个段。

.text 表示代码段。.data 初始化的数据段。.bss 未初始化的数据段。 .rodata 只读数据段。

可以自己使用.section 来定义一个段,每个段以段名开始,以下一段名或者文件结 尾结束

常见的伪操作有:

.byte 定义单字节数据,比如.byte 0x12。 .short 定义双字节数据,比如.short 0x1234。 .long 定义一个 4 字节数据,比如.long 0x12345678。 .equ 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。 .align 数据字节对齐,比如:.align 4 表示 4 字节对齐。 .end 表示源文件结束。 .global 定义一个全局符号,格式为:.global symbol,比如:.global _start。

GNU 汇编同样也支持函数,函数格式如下:

函数名:

函数体 

​ 返回语句

stm32_第8张图片

“Undefined_Handler”就是函数名,“ldr r0, =Undefined_Handler”是函数体,“bx r0”是函数 返回语句,“bx”指令是返回指令,函数返回语句不是必须的。

2、Cortex-A7 常用汇编指令

2.1、 处理器内部数据传输指令

使用处理器做的最多事情就是在处理器内部来回的传递数据,常见的操作有:

①、将数据从一个寄存器传递到另外一个寄存器。

②、将数据从一个寄存器传递到特殊寄存器,如 CPSR 和 SPSR 寄存器。

③、将立即数传递到寄存器。 数据传输常用的指令有三个:MOV、MRS 和 MSR,

stm32_第9张图片

2.2 存储器访问指令

ARM 不能直接访问存储器,比如 RAM 中的数据,I.MX6UL 中的寄存器就是 RAM 类型 的,我们用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值 写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器中。读取 I.MX6UL 寄存器也是一样的,只是过程相反。常用的存储器访问指令有两种:LDR 和 STR。

stm32_第10张图片

stm32_第11张图片

stm32_第12张图片

2.3、 压栈和出栈指令

通常会在 A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。要想 再跳回 A 函数以后代码能够接着正常运行,那就必须在跳到 B 函数之前将当前处理器状态保存 起来(就是保存 R0~R15 这些寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复 R0~R15 即可。保存 R0~R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做 恢复现场。在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。压栈 的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令,即可以一次 操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址。

假如我们现在要将 R0~R3 和 R12 这 5 个寄存器压栈,当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,使用的汇编代码如下:PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈

stm32_第13张图片

假如我们现在要再将 LR 进行压栈,汇编代码如下:PUSH {LR} @将 LR 进行压栈

stm32_第14张图片

如果我们要出栈的话 就是使用如下代码:

POP {LR} @先恢复 LR

POP {R0~R3,R12} @在恢复 R0~R3,R12

出栈的就是从栈顶,也就是 SP 当前执行的位置开始,地址依次减小来提取堆栈中的数据 到要恢复的寄存器列表中。

PUSH 和 POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”,

stm32_第15张图片

2.4、跳转指令

有多种跳转操作,比如: ①、直接使用跳转指令 B、BL、BX 等。 ②、直接向 PC 寄存器里面写入数据。 上述两种方法都可以完成跳转操作,但是一般常用的还是 B、BL 或 BX,

stm32_第16张图片

2.4.1 、B指令

B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指 令,ARM 处理器就会立即跳转到指定的目标地址。如果要调用的函数不会再返回到原来的执行 处,那就可以用 B 指令

stm32_第17张图片

上述代码就是典型的在汇编中初始化 C 运行环境,然后跳转到 C 文件的 main 函数中运行,

2.4.2、BL指令

BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以 通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用 一个基本但常用的手段。比如 Cortex-A 处理器的 irq 中断服务函数都是汇编写的,主要用汇编 来实现现场的保护和恢复、获取中断号等。但是具体的中断处理过程都是 C 函数,所以就会存 在汇编中调用 C 函数的问题。而且当 C 语言版本的中断处理函数执行完成以后是需要返回到 irq 汇编中断服务函数,因为还要处理其他的工作,一般是恢复现场。这个时候就不能直接使用 B 指令了,因为 B 指令一旦跳转就再也不会回来了,这个时候要使用 BL 指令。

stm32_第18张图片

2.5、算术运算指令

stm32_第19张图片

2.6、逻辑运算指令

stm32_第20张图片

四、汇编LED灯实验

使用库函数来初始化 STM32 的一个 IO 为输出功能,代 码中重点要做的事情有以下几个:

①、使能指定 GPIO 的时钟。

②、初始化 GPIO,比如输出功能、上拉、速度等等。

③、STM32 有的 IO 可以作为其它外设引脚,也就是 IO 复用,如果要将 IO 作为其它外设 引脚使用的话就需要设置 IO 的复用功能。

④、最后设置 GPIO 输出高电平或者低电平。

1、I.MX6U IO 命名

I.MX6ULL 的 IO 分为两类:SNVS 域的和通用的,这两类 IO 本 质上都是一样的。

形如“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.MX6ULL 的 GPIO 并不像 STM32 一样以 PA0~15 这样命名,他是根据某个 IO 所拥有的功能来命名的。

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。

2、I.MX6U IO 配置

stm32_第21张图片

stm32_第22张图片

HYS(bit16):对应图 8.1.4.2 中 HYS,用来使能迟滞比较器,当 IO 作为输入功能的时候有 效,用于设置输入接收器的施密特触发器是否使能。如果需要对输入波形进行整形的话可以使 能此位。此位为 0 的时候禁止迟滞比较器,为 1 的时候使能迟滞比较器。

PUS(bit15:14):对应图 8.1.4.2 中的 PUS,用来设置上下拉电阻的,一共有四种选项可以选 择,如表 8.1.4.1 所示:

stm32_第23张图片

PUE(bit13):图 8.1.4.2 没有给出来,当 IO 作为输入的时候,这个位用来设置 IO 使用上下 拉还是状态保持器。当为 0 的时候使用状态保持器,当为 1 的时候使用上下拉。状态保持器在 IO 作为输入的时候才有用,顾名思义,就是当外部电路断电以后此 IO 口可以保持住以前的状 态。

PKE(bit12):对应图 8.1.4.2 中的 PKE,此位用来使能或者禁止上下拉/状态保持器功能,为 0 时禁止上下拉/状态保持器,为 1 时使能上下拉和状态保持器。

ODE(bit11):对应图 8.1.4.2 中的 ODE,当 IO 作为输出的时候,此位用来禁止或者使能开 路输出,此位为 0 的时候禁止开路输出,当此位为 1 的时候就使能开路输出功能。

SPEED(bit7:6):对应图 8.1.4.2 中的 SPEED,当 IO 用作输出的时候,此位用来设置 IO 速 度,设置如表 8.1.4.2 所示:

stm32_第24张图片

DSE(bit5:3):对应图 8.1.4.2 中的 DSE,当 IO 用作输出的时候用来设置 IO 的驱动能力, 总共有 8 个可选选项,如表 8.1.4.3 所示:

stm32_第25张图片

SRE(bit0):对应图 8.1.4.2 中的 SRE,设置压摆率,当此位为 0 的时候是低压摆率,当为 1 的时候是高压摆率。这里的压摆率就是 IO 电平跳变所需要的时间,比如从 0 到 1 需要多少时 间,时间越小波形就越陡,说明压摆率越高;反之,时间越多波形就越缓,压摆率就越低。如 果你的产品要过 EMC 的话那就可以使用小的压摆率,因为波形缓和,如果你当前所使用的 IO 做高速通信的话就可以使用高压摆率。

3、I.MX6U GPIO 配置

GPIO 是一个 IO 众多复用功能中的一种,比 如 GPIO1_IO00 这个 IO 可以复用为:I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID、 ENET1_REF_CLK 、 MQS_RIGHT 、 GPIO1_IO00 、 ENET1_1588_EVENT0_IN 、 SRC_SYSTEM_RESET 和 WDOG3_WDOG_B 这 9 个功能,GPIO1_IO00 是其中的一种,我们 想要把 GPIO1_IO00 用作哪个外设就复用为哪个外设功能即可。

stm32_第26张图片

左上角部分的 GPIO 框图就是,当 IO 用作 GPIO 的时候需要设置的寄存器,一共有八个: DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR。

1、DR 寄存器,此寄存器是数据寄存器:

stm32_第27张图片

此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应 一个 GPIO。当 GPIO 被配置为输出功能以后,向指定的位写入数据那么相应的 IO 就会输出相 应的高低电平,比如要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1。当 GPIO被配置为输入模式以后,此寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO,例如, 当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0。

2、GDIR 寄存器,这是方向寄存器:stm32_第28张图片

GDIR 寄存器也是 32 位的,此寄存器用来设置某个 IO 的工作方向,是输入还是输出。同 样的,每个 IO 对应一个位,如果要设置 GPIO 为输入的话就设置相应的位为 0,如果要设置为 输出的话就设置为 1。比如要设置 GPIO1_IO00 为输入,那么 GPIO1.GDIR=0;

3、PSR 寄存器,这是 GPIO 状态寄存器:

stm32_第29张图片

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

4、ICR1和ICR2这两个寄存器,都是中断控制寄存器,

ICR1用于配置低16个GPIO, ICR2 用于配置高 16 个 GPIO。

stm32_第30张图片

ICR1 用于 IO0~15 的配置, ICR2 用于 IO16~31 的配置。ICR1 寄存器中一个 GPIO 用两个 位,这两个位用来配置中断的触发方式,和 STM32 的中断很类似。

stm32_第31张图片

5、 IMR 寄存器,这是中断屏蔽寄存器。

stm32_第32张图片

IMR 寄存器也是一个 GPIO 对应一个位,IMR 寄存器用来控制 GPIO 的中断禁止和使能, 如果使能某个 GPIO 的中断,那么设置相应的位为 1 即可,反之,如果要禁止中断,那么就设 置相应的位为 0 即可。

6、寄存器 ISR,ISR 是中断状态寄存器

stm32_第33张图片

ISR 寄存器也是 32 位寄存器,一个 GPIO 对应一个位,只要某个 GPIO 的中断发生,那么 ISR 中相应的位就会被置 1。所以,我们可以通过读取 ISR 寄存器来判断 GPIO 中断是否发生, 相当于 ISR 中的这些位就是中断标志位。当我们处理完中断以后,必须清除中断标志位,清除 方法就是向 ISR 中相应的位写 1,也就是写 1 清零。

7、EDGE_SEL 寄存器,这是边沿选择寄存器

stm32_第34张图片

EDGE_SEL 寄存器用来设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一 个 GPIO 对应一个位。如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降 沿(双边沿)触发。

4、I.MX6U GPIO 时钟使能

STM32 的每个外设都有 一个外设时钟,GPIO 也不例外,要使用某个外设,必须要先使能对应的时钟。I.MX6U 其实也 一样的,每个外设的时钟都可以独立的使能或禁止,这样可以关闭掉不使用的外设时钟,起到 省电的目的。

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

stm32_第35张图片

CCM_CCGR0 是个 32 位寄存器,其中每 2 位控制一个外设的时钟,比如 bit31:30 控制着 GPIO2 的外设时钟,两个位就有 4 种操作方式,

stm32_第36张图片

要将 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,设置输入/输出、是否使 用中断、默认输出电平等。

你可能感兴趣的:(stm32,嵌入式硬件,单片机)