代码解读之fsl_gpio

读fsl_gpio.c 和 fsl_gpio.h 代码

使用kw38的win mcuxpresso版本 SDK_2_6_615_FRDM-KW38_mcuxpresso_win

fsl_gpio.h

1
2
3
#ifndef _FSL_GPIO_H_
#define _FSL_GPIO_H_
#include "fsl_common.h"

结构体

Part1 gpio_pin_direction_t 和 gpio_checker_attribute_t

1
2
3
4
5
6
7
8
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
} gpio_pin_direction_t;

typedef enum _gpio_checker_attribute{
}gpio_checker_attribute_t;

gpio_pin_direction_t 确定Pin引脚方向,输入为0,输出为1。

GPIO 检查器属性用于某些具有 GPIO 属性检查器功能的 NXP 微控制器。此功能用于安全目的,根据访问属性检查是否允许访问 GPIO 引脚

gpio_checker_attribute_t 枚举定义了可以检查的可能属性。这些属性指定不同权限级别(用户非安全、用户安全和特权安全)的读取和写入权限。

另外还有一个属性值kGPIO_IgnoreAttributeCheck,表示忽略属性检查。

GPIO 检查器属性与 GPIO_CheckAttribute() 函数结合使用,以根据操作的属性检查是否允许 GPIO 引脚上的特定操作

Part2 gpio_pin_config_t 和 gpio_interrupt_config_t

1
2
3
4
5
6
7
8
typedef struct _gpio_pin_config
{
gpio_pin_direction_t pinDirection;
uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */
} gpio_pin_config_t;

typedef enum _gpio_interrupt_config{
} gpio_interrupt_config_t;

这是一个 C 语言代码片段,它定义了两个数据结构和一个枚举类型,用于在微控制器上配置通用输入/输出 (GPIO) 引脚。

  1. gpio_pin_config_t 定义了 GPIO 引脚的配置参数,包括它的方向(输入或输出)和它的默认输出逻辑(如果它是一个输出引脚)
  2. 第二个数据结构 gpio_interrupt_config_t 是有条件地定义的,具体取决于微控制器是否支持其 GPIO 引脚上的中断。如果是,则此结构定义中断生成条件的配置参数。
  3. 枚举类型 gpio_interrupt_config_t 定义了中断生成条件的可能值,例如在上升沿、下降沿、任一边沿或逻辑电平为高或低时启用中断。

函数接口

GPIO配置

Part1 GPIO_PinInit()

这是名为 GPIO_PinInit() 的函数的代码片段,它是用于处理微控制器上的通用输入/输出 (GPIO) 引脚的更大驱动程序的一部分。该驱动程序提供一组函数来配置、读取和写入 GPIO 引脚

函数 GPIO_PinInit() 初始化板使用的 GPIO 引脚。它采用三个参数:

  • GPIO 外设的基地址 GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
  • GPIO 端口的引脚号 GPIO port pin number
  • 以及指向定义 GPIO 引脚配置的 gpio_pin_config_t 结构的指针 GPIO pin configuration pointer

gpio_pin_config_t 结构包含两个字段:

  • pinDirection:GPIO引脚的方向,可以设置为kGPIO_DigitalInput或kGPIO_DigitalOutput。
  • outputLogic:GPIO引脚的输出逻辑电平,仅在引脚配置为数字输出时适用。它可以设置为 0 或 1。

函数 GPIO_PinInit() 使用 gpio_pin_config_t 结构中定义的配置初始化 GPIO 引脚。

GPIO输入操作

Part2 静态函数 GPIO_PinWrite()

这是名为 GPIO_PinWrite() 的函数的代码片段。

函数GPIO_PinWrite()将一个GPIO引脚的输出电平设置为逻辑1或逻辑0。它需要三个参数:

  • GPIO外设的基址、
  • GPIO端口的引脚号、
  • GPIO引脚的输出电平.

输出参数可以设置为 0 或 1 以指定 GPIO 引脚的输出逻辑电平。如果输出为 0,则相应的引脚输出设置为逻辑低电平,否则,如果输出为 1,则相应的引脚输出设置为逻辑高电平

函数 GPIO_PinWrite() 使用按位操作来设置 GPIO 引脚的输出电平。如果输出参数为0,则使用左移操作清除GPIO端口输出清除寄存器(GPIOx_PCOR)中的相应位。否则,如果输出参数为 1,则使用左移操作设置 GPIO 端口输出设置寄存器 (GPIOx_PSOR) 中的相应位。

此代码是用 C 编程语言编写的,并假定微控制器具有 GPIO 寄存器的特定实现,例如分别用于清除和设置 GPIO 输出引脚的 PCOR 和 PSOR 寄存器。

Part3 静态函数 GPIO_PortSet()

这是名为 GPIO_PortSet() 的函数的代码片段.

函数 GPIO_PortSet() 将多个 GPIO 引脚的输出电平设置为逻辑 1。它有两个参数:

  • GPIO 外设的基址, base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
  • 指定要设置哪些 GPIO 引脚的掩码。GPIO pin number macro

掩码参数是一个位掩码,指示要设置的引脚。掩码参数的每一位对应一个特定的 GPIO 引脚。如果某位设置为 1,则相应的 GPIO 引脚输出设置为逻辑高电平

函数 GPIO_PortSet() 通过使用按位或运算写入 GPIO 端口输出设置寄存器 (GPIOx_PSOR),将指定 GPIO 引脚的输出电平设置为逻辑 1。在执行按位或操作之前,将掩码参数的值左移以与 GPIO 端口输出设置寄存器的位位置对齐。

此代码是用 C 编程语言编写的,并假定微控制器具有 GPIO 寄存器的特定实现,例如用于设置 GPIO 输出引脚的 PSOR 寄存器。

Part4 静态函数 GPIO_PortClear()

这是名为 GPIO_PortClear() 的函数的代码片段.

函数 GPIO_PortClear() 将多个 GPIO 引脚的输出电平设置为逻辑 0。它有两个参数:

  • GPIO 外设的基址
  • 和指定要清除哪些 GPIO 引脚的掩码。

掩码参数是一个位掩码,指示要清除哪些引脚。掩码参数的每一位对应一个特定的 GPIO 引脚。如果某位设置为0,则相应的 GPIO 引脚输出设置为逻辑低电平。

函数 GPIO_PortClear() 通过使用按位或运算写入 GPIO 端口输出清除寄存器 (GPIOx_PCOR),将指定 GPIO 引脚的输出电平设置为逻辑 0。在执行按位或操作之前,将掩码参数的值左移以与 GPIO 端口输出清除寄存器的位位置对齐。

此代码是用 C 编程语言编写的,并假定微控制器具有 GPIO 寄存器的特定实现,例如用于清除 GPIO 输出引脚的 PCOR 寄存器。

Part5 静态函数 GPIO_PortToggle()

这是名为 GPIO_PortToggle() 的函数的代码片段。

函数 GPIO_PortToggle() 反转多个 GPIO 引脚的当前输出逻辑。它有两个参数:

  • GPIO 外设的基地址
  • 和一个掩码,它指定要切换的 GPIO 引脚。

掩码参数是一个位掩码,指示要切换的引脚。掩码参数的每一位对应一个特定的 GPIO 引脚。如果某位设置为 1,则相应的 GPIO 引脚输出逻辑反转,即如果设置为逻辑 1,则变为逻辑 0,反之亦然。

函数 GPIO_PortToggle() 通过使用按位或运算写入 GPIO 端口输出切换寄存器 (GPIOx_PTOR) 来反转指定 GPIO 引脚的输出逻辑。在执行按位或操作之前,掩码参数的值左移以与 GPIO 端口输出切换寄存器的位位置对齐。

此代码是用 C 编程语言编写的,并假定微控制器具有 GPIO 寄存器的特定实现,例如用于切换 GPIO 输出引脚的 PTOR 寄存器。

GPIO输入操作

Part6 静态函数 GPIO_PinRead()

这是一个名为 GPIO_PinRead() 的函数的代码片段。

函数 GPIO_PinRead() 读取单个 GPIO 引脚的当前输入值。它需要两个参数:GPIO外设的基地址和要读取的GPIO引脚的引脚号。

函数 GPIO_PinRead() 通过使用移位和与操作从 GPIO 端口输入数据寄存器 (GPIOx_PDIR) 读取来读取指定 GPIO 引脚的输入值。按位移位操作将 GPIO 端口输入数据寄存器的值右对齐,以与指定 GPIO 引脚的位位置对齐。 AND 运算会屏蔽除对应于指定 GPIO 引脚的位之外的所有位

该函数将指定 GPIO 引脚的输入值作为single-bit值(0 或 1)返回。

此代码是用 C 编程语言编写的,并假定微控制器具有 GPIO 寄存器的特定实现,例如用于读取 GPIO 输入引脚的 PDIR 寄存器。

GPIO中断

GPIO_PortGetInterruptFlags() 和 GPIO_PortClearInterruptFlags()

此代码提供了一个 API,用于配置和处理 GPIO 引脚上的中断。

前两个函数 GPIO_PortGetInterruptFlags()GPIO_PortClearInterruptFlags() 分别用于读取和清除 GPIO 端口中多个引脚的中断状态标志

base参数是指GPIO peripheral的基地址,mask参数是用来指定要对哪个GPIO引脚进行读或清除操作。

此语句似乎描述了与数字系统中的 DMA 请求或电平敏感中断相关联的标志的行为。

如果某个引脚被配置为生成 DMA 请求,则当请求的 DMA 传输完成时,相应的标志将自动清除。这意味着该标志指示 DMA 传输的状态,并在传输完成时重置。

另一方面,如果引脚未配置为生成 DMA 请求,则相应的标志将保持设置状态,直到将逻辑 1 写入该标志。这意味着该标志可用于指示与 DMA 无关的事件的发生,例如中断或数据传输。

最后,如果引脚被配置为电平敏感中断并且中断信号保持有效,则标志立即再次设置。此行为允许系统响应连续信号,例如按钮按下或传感器读数,而不会错过任何事件。

GPIO_SetPinInterruptConfig() 和 GPIO_GetPinsDMARequestFlags() GPIO_SetMultipleInterruptPinsConfig()

其余函数是有条件的,取决于 GPIO 端口是否支持中断。如果支持中断,则 GPIO_SetPinInterruptConfig() 函数用于设置单个引脚的中断配置。 pin 参数指定 GPIO 引脚号,而 config 参数用于指定中断配置。

GPIO_SetPinInterruptConfig() 函数用于读取多个引脚的 DMA 请求标志GPIO_SetMultipleInterruptPinsConfig() 函数用于同时设置多个引脚的中断配置。 mask 参数用于指定要为其设置中断配置的 GPIO 引脚,而 config 参数指定中断配置。

中断配置选项包括设置中断/DMA 请求、触发中断/DMA 请求的边沿类型、触发中断的逻辑电平以及输出触发模式

GPIO_CheckAttributeBytes()

此代码片段定义了一个名为 GPIO_CheckAttributeBytes() 的函数。该函数有两个参数:一个指向 GPIO 外设(基)的指针和一个名为 attribute 的 gpio_checker_attribute_t 参数。

该函数检查 GPIO 模块是否具有设备特定数量的数据端口,以及它是否支持属性检查器。如果满足这些条件,该函数将继续检查成功访问指定 GPIO 引脚(掩码)的 GPIO 编程模型所需的字节级属性。

属性参数是一个枚举,表示 GACR 中 4 个数据字节的属性控制值。字节级属性是使用小端数据约定定义的。

fgpio_driver 快速GPIO

FGPIO_PortInit()

此代码片段介绍了 FGPIO 功能,该功能仅在某些 Kinetis MCU 上受支持。 FGPIO 寄存器是 IOPORT 接口的别名,通过 IOPORT 接口的访问与任何指令获取并行发生,并在一个周期内完成。此内存映射称为 FGPIO

然后代码定义了一个名为 FGPIO_PortInit() 的函数,该函数将指向 FGPIO 外设(基)的指针作为其参数。此函数通过关闭其时钟来初始化 FGPIO 外设

FGPIO_Type 可能是表示 FGPIO 外设的结构的类型定义。特定的 FGPIO 外设用后缀(FGPIOA、FGPIOB、FGPIOC 等)表示,并且可能具有不同的配置和引脚映射。

还有一个条件预处理器指令,用于检查 FSL_FEATURE_SOC_FGPIO_COUNT 功能是否已定义和支持。如果不支持,则不会编译指令中的代码。

同样,还有另一个条件预处理器指令检查 FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL 功能是否已定义和支持。如果不支持,则不会编译指令中的代码。

总的来说,这段代码设置了 FGPIO 功能并提供了一个函数来初始化 FGPIO 外设。但是,如果没有关于如何使用此代码以及 FGPIO_Type 结构是什么样子的更多上下文,则很难提供更详细的分析。

fsl_gpio.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;

static uint32_t GPIO_GetInstance(GPIO_Type *base)
{
uint32_t instance;

/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++)
{
if (s_gpioBases[instance] == base)
{
break;
}
}

assert(instance < ARRAY_SIZE(s_gpioBases));

return instance;
}

void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(NULL != config);

uint32_t u32flag = 1;

if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(u32flag << pin);
}
else
{
GPIO_PinWrite(base, pin, config->outputLogic);
base->PDDR |= (u32flag << pin);
}
}

uint32_t GPIO_PortGetInterruptFlags(GPIO_Type *base)
{
uint8_t instance;
PORT_Type *portBase;
instance = (uint8_t)GPIO_GetInstance(base);
portBase = s_portBases[instance];
return portBase->ISFR;
}

void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t mask)
{
uint8_t instance;
PORT_Type *portBase;
instance = (uint8_t)GPIO_GetInstance(base);
portBase = s_portBases[instance];
portBase->ISFR = mask;
}

void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute)
{
base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) |
((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT);
}
作者

Gavin

发布于

2023-03-21

更新于

2023-03-21

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×