设计说明
源码说明
GPIO HAL 层相关.c和.h文件分别位于 luban-lite\bsp\artinchip\hal\gpio 和 luban-lite\bsp\artinchip\include\hal 目录。 Driver 层相关.c和.h 文件分别位于 luban-lite\bsp\artinchip\drv\gpio 和luban-lite\bsp\artinchip\include\drv目录。 主要源文件说明如下:
文件 | 说明 |
---|---|
aic_hal_gpio.h | GPIO HAL 层 API 的头文件 |
aic_hal_gpio.c | GPIO HAL 层 API 的实现 |
aic_drv_gpio.h | GPIO DRV 层 API 的头文件 |
aic_drv_gpio.c | GPIO driver 注册以及 GPIO DRV 层 API 的实现 |
aic_hal_gpio_def_v10.c | GPIO V1.0 的配置 |
aic_hal_gpio_def_v11.c | GPIO V1.1 的配置 |
aic_hal_gpio_def_v12.c | GPIO V1.2 的配置 |
模块架构
GPIO 驱动 Driver 层采用 RT-Thread 的 PIN设备驱动框架,如果只使用HAL层也可以支持 Baremetal 方式的应用场景。
1.GPIO HAL 层。提供了 PinMux 和通用 GPIO 功能寄存器级的功能封装。2.GPIO Driver 层。
RT-Thread。通用 GPIO 功能注册成 RTT Pin driver,PinMux 直接以 API 的形式提供。
BareMental。客户自定义 Driver 直接调用 GPIO HAL 层 API。
RTT Pin 驱动
RT-Thread 调用 rt_device_pin_register() 把通用 GPIO 功能注册成 Pin Driver,Pin Driver 提供了以下功能:
模式配置。配置输入、输出模式,输入上下拉配置。
读取端口状态。读取输入端口的电平状态。
设置端口状态。配置输出端口的电平状态。
GPIO 中断配置。注册中断,使能中断。
因为一个系统只允许注册一个 Pin Device,所以在调用的时候除了先使用 rt_device_find() 查找 Device 的形式来调用功能,也可以直接使用一组 rt_pin_xxx() 的函数直接来调用功能。
关键流程设计
初始化流程
RT-Thread 系统初始化时会自动调用 GPIO 驱动初始化函数:
Reset_Handler
→ entry()
→ rtthread_startup()
→ rt_hw_board_init()
→ rt_components_board_init()
→ drv_pin_init()
2
3
4
5
6
drv_pin_init() 注册了 RTT Pin 驱动:
const static struct rt_pin_ops _drv_pin_ops =
{
drv_pin_mode,
drv_pin_write,
drv_pin_read,
#ifdef AIC_GPIO_IRQ_DRV_EN
drv_pin_attach_irq,
drv_pin_detach_irq,
drv_pin_irq_enable,
#else
RT_NULL,
RT_NULL,
RT_NULL,
#endif
drv_pin_get,
};
int drv_pin_init(void)
{
int ret = RT_EOK;
ret = rt_device_pin_register("pin", &_drv_pin_ops, RT_NULL);
return ret;
}
INIT_BOARD_EXPORT(drv_pin_init);
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
GPIO IRQ 流程
Luban-Lite 对 GPIO IRQ 做了一个二级中断的封装:1.一级中断。每个 GPIO Group 共享一个物理中断号,每个 GPIO Group 最多包含 32 个 GPIO Pin 脚。
2.二级中断。每个 GPIO Pin 脚中断也虚拟成标准的 Luban-Lite 中断,但是实际上是 GPIO Group ISR 做了一次中转。
接口设计
Driver 层接口设计
以下接口是 Pin 设备驱动框架的标准接口。
struct rt_pin_ops
{
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);
void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);
int (*pin_read)(struct rt_device *device, rt_base_t pin);
rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,
rt_uint32_t mode, void (*hdr)(void *args), void *args);
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);
rt_base_t (*pin_get)(const char *name);
};
2
3
4
5
6
7
8
9
10
11
drv_pin_mode
函数原型 | void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode) |
---|---|
功能说明 | 设置 Pin 模式,包括输入/输出模式、上下拉模式 |
参数定义 | pin:Pin id mode: 输入/输出模式、上下拉模式 (PIN_MODE_xxx 格式的宏) |
注意事项 |
drv_pin_write
函数原型 | void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_base_t value) |
---|---|
功能说明 | 设置输出 Pin 的电平状态 |
参数定义 | pin:Pin id value: 电平状态 0/1 |
注意事项 |
drv_pin_read
函数原型 | int drv_pin_read(struct rt_device *device, rt_base_t pin) |
---|---|
功能说明 | 设置输出 Pin 的电平状态 |
参数定义 | pin:Pin id |
返回值 | 电平状态 0/1 |
注意事项 |
drv_pin_attach_irq
函数原型 | rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) |
---|---|
功能说明 | Pin 注册中断 |
参数定义 | pin:Pin id mode: 中断触发模式,边沿还是电平触发 (PIN_IRQ_MODE_xxx 格式的宏)hdr:pin 中断处理函数 args:中断处理时的自定义参数 |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
drv_pin_detach_irq
函数原型 | rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_int32_t pin) |
---|---|
功能说明 | Pin 注销中断 |
参数定义 | pin:Pin id |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
drv_pin_irq_enable
函数原型 | rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) |
---|---|
功能说明 | 使能 Pin 中断 |
参数定义 | pin:Pin id enabled: 1 = en, 0 = dis |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
drv_pin_get
函数原型 | rt_base_t drv_pin_get(const char *name) |
---|---|
功能说明 | 根据 Pin Name 获取 Pin Id |
参数定义 | name:Pin Name 字符串 (“PA.1” 类似格式) |
返回值 | Pin Id |
注意事项 |
HAL 层接口设计
hal_gpio_set_func
函数原型 | int hal_gpio_set_func(unsigned int group, unsigned int pin, unsigned int func) |
---|---|
功能说明 | 设置 Pin 的 Function 模式 |
参数定义 | group:group id pin:offset in group func: 0 = 关闭, 1 = 通用 GPIO, 2~8 = 专用功能 |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
hal_gpio_get_func
函数原型 | int hal_gpio_get_func(unsigned int group, unsigned int pin, unsigned int *pfunc) |
---|---|
功能说明 | 获取 Pin 的 Function 模式 |
参数定义 | group:group id pin:offset in group func: 0 = 关闭, 1 = 通用 GPIO, 2~8 = 专用功能 |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
hal_gpio_direction_inpu
函数原型 | int hal_gpio_direction_input(unsigned int group, unsigned int pin) |
---|---|
功能说明 | 设置 Pin 为输入模式 |
参数定义 | group:group id pin:offset in group |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
hal_gpio_direction_output
函数原型 | int hal_gpio_direction_output(unsigned int group, unsigned int pin) |
---|---|
功能说明 | 设置 Pin 为输出模式 |
参数定义 | group:group id pin:offset in group |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
hal_gpio_set_bias_pull
函数原型 | int hal_gpio_set_bias_pull(unsigned int group, unsigned int pin, unsigned int pull) |
---|---|
功能说明 | 设置 Pin 的上下拉模式 |
参数定义 | group:group id pin:offset in group pull: 0 = 关闭, 2 = 下拉, 3 = 上拉 |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
hal_gpio_set_drive_strength
函数原型 | int hal_gpio_set_drive_strength(unsigned int group, unsigned int pin, unsigned int strength) |
---|---|
功能说明 | 设置 Pin 的驱动能力 |
参数定义 | group:group id pin:offset in group strength: 0 ~ 7 |
注意事项 |
hal_gpio_set_debounce
函数原型 | int hal_gpio_set_debounce(unsigned int group, unsigned int pin, unsigned int debounce) |
---|---|
功能说明 | 设置 Pin 的中断模式 |
参数定义 | group:group id pin:offset in group debounce: 0 ~ 0xFFF |
注意事项 |
hal_gpio_set_irq_mode
函数原型 | int hal_gpio_set_irq_mode(unsigned int group, unsigned int pin, unsigned int irq_mode) |
---|---|
功能说明 | 设置 Pin 的中断模式 |
参数定义 | group:group id pin:offset in group irq_mode: 0 = 下降沿,1 = 上升沿,2 = 低电平,3 = 高电平,4 = 双沿 |
返回值 | 操作是否成功 (0=OK, other=Error) |
注意事项 |
Demo
此Demo是test_gpio 命令的部分代码,含二级中断使用方法(详见 test_gpio.c),可以作为 GPIO 的使用参考:
static u32 test_gpio_input_pin_cfg(char *arg_pin)
{
// 1.test_gpio_pin_check函数获取引脚号
static u32 pin = 0;
pin = test_gpio_pin_check(arg_pin, GPIO_SET_MODE_FLAG);
// 2.引脚模式设置为Input-PullUp模式,即上拉输入模式
rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
// 3.rt_pin_attach_irq函数将中断处理程序test_gpio_input_irq_handler附加到引脚上,并设置中断触发模式为上升沿和下降沿
rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING_FALLING,
test_gpio_input_irq_handler, &pin);
// 4.rt_pin_irq_enable函数启用引脚的中断功能
rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
return pin;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18