本帖最后由 bzhou830 于 2023-10-13 10:28 编辑
本文首先介绍LHAL库的概念,继而使用小安排的GPIO外设。并使用raspberry pi pico作为逻辑分析仪来对GPIO的输出做采样捕获验证。
1. LHAL库外设
博流的LHAL库驱动外设进行了统一的封装。下列表格则是从SDK文档中摘取出来,列举出来小安排使用的BL616芯片外设的在LHAL库中的支持。
其中: √表示已支持,×表示未支持,-表示该芯片没有该外设
parameter |
BL616/BL618 |
ADC |
√ |
CAM |
× |
CKS |
√ |
DAC |
√ |
DMA |
√ |
EFUSE |
√ |
EMAC |
√ |
FLASH |
√ |
GPIO |
√ |
I2C |
√ |
IR |
√ |
MJPEG |
√ |
PWM_v1 |
- |
PWM_v2 |
√ |
RTC |
√ |
SEC_AES |
√ |
SEC_SHA |
√ |
SEC_TRNG |
√ |
SEC_PKA |
√ |
SPI |
√ |
TIMER |
√ |
UART |
√ |
USB_v1 |
- |
USB_v2 |
√ |
WDG |
√ |
上述表格中的所有外设都是使用同一个结构体对其进行配置的:
struct bflb_device_s {
const char *name; //外设名称
uint32_t reg_base; //外设寄存器基地址
uint8_t irq_num; //外设中断号
uint8_t idx; //外设 id,例如 UART0、UART1
uint8_t sub_idx; //外设子id,例如 DMA0_CH0、DMA0_CH1
uint8_t dev_type; //外设类型
void *user_data; //用户数据
};
或者外设对象提供了两个方法:
1.通过外设名称获取
struct bflb_device_s *bflb_device_get_by_name(const char *name)
2.通过外设类型和外设id获取
struct bflb_device_s *bflb_device_get_by_id(uint8_t type, uint8_t idx)
这两个函数的实现可以在aithinker_Ai-M6X_SDK\drivers\lhal\config\bl616\device_table.c
中找到,如下图所示:
2. GPIO配置
有了上面的基础了解之后我们大概就清楚了,如果想要使用gpio外设,那么首先我们就需要get到gpio设备。随后就是用get到的设备进行初始化。sdk中提供的初始化的函数定义如下:
void bflb_gpio_init(struct bflb_device_s *dev, uint8_t pin, uint32_t cfgset);
- 第一个参数就是前面我们通过get得到的gpio设备;
- 第二个参数是对应到硬件上的端口号;
- 第三个参数是将这个pin设置成具体的模式和功能(包括gpio mode、gpio function、gpio pupd、gpio smt、gpio drive)。这些设置可以通过位或的方式进行设置。下列是从sdk中摘录的具体的每个域的设置参数。
// gpio mode
#define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* Input Enable */
#define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* Output Enable */
#define GPIO_ANALOG (2 << GPIO_MODE_SHIFT) /* Analog Enable */
#define GPIO_ALTERNATE (3 << GPIO_MODE_SHIFT) /* Alternate Enable */
// gpio pupd
#define GPIO_FLOAT (0 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */
#define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */
#define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */
// gpio smt
#define GPIO_SMT_DIS (0 << GPIO_SMT_SHIFT)
#define GPIO_SMT_EN (1 << GPIO_SMT_SHIFT)
// gpio drive
#define GPIO_DRV_0 (0 << GPIO_DRV_SHIFT)
#define GPIO_DRV_1 (1 << GPIO_DRV_SHIFT)
#define GPIO_DRV_2 (2 << GPIO_DRV_SHIFT)
#define GPIO_DRV_3 (3 << GPIO_DRV_SHIFT)
// gpio init trig mode
#define GPIO_INT_TRIG_MODE_SYNC_FALLING_EDGE 0
#define GPIO_INT_TRIG_MODE_SYNC_RISING_EDGE 1
#define GPIO_INT_TRIG_MODE_SYNC_LOW_LEVEL 2
#define GPIO_INT_TRIG_MODE_SYNC_HIGH_LEVEL 3
#define GPIO_INT_TRIG_MODE_SYNC_FALLING_RISING_EDGE 4
#define GPIO_INT_TRIG_MODE_ASYNC_FALLING_EDGE 8
#define GPIO_INT_TRIG_MODE_ASYNC_RISING_EDGE 9
#define GPIO_INT_TRIG_MODE_ASYNC_LOW_LEVEL 10
#define GPIO_INT_TRIG_MODE_ASYNC_HIGH_LEVEL 11
// gpio uart function
#define GPIO_UART_FUNC_UART0_RTS 0
#define GPIO_UART_FUNC_UART0_CTS 1
#define GPIO_UART_FUNC_UART0_TX 2
#define GPIO_UART_FUNC_UART0_RX 3
#define GPIO_UART_FUNC_UART1_RTS 4
#define GPIO_UART_FUNC_UART1_CTS 5
#define GPIO_UART_FUNC_UART1_TX 6
#define GPIO_UART_FUNC_UART1_RX 7
顺便看看和初始化相关的几个函数
void bflb_gpio_deinit(struct bflb_device_s *dev, uint8_t pin); //反初始化,相当于回到init之前的状态。io设置为浮空
void bflb_gpio_set(struct bflb_device_s *dev, uint8_t pin); //设置为高电平
void bflb_gpio_reset(struct bflb_device_s *dev, uint8_t pin); //设置为低电平
bool bflb_gpio_read(struct bflb_device_s *dev, uint8_t pin); //读取io电平
3. GPIO配置示例
现在我们就来找一个io对其进行配置,让其间歇性的输出高低电平。随后使用逻辑分析仪来验证我们程序是否正常。
找到小安派的原理图,我们看看IO0是否引出了。
从上图中看到IO0对应对应原理图中标号为I2C_SCL_TOP的网络,我们直接在原理图文件里面搜索,可以找到在J9这个连接件上是接着I2C_SCL_TOP的。
那对应在板子的哪个位置呢?我们再来打开小安派的PCB文件,为了方便查看,先移除掉覆铜。这就看到了这个I2C_SCL_TOP对应在板子上的位置了。
很幸运,这个接口是可以连接的。那么我们就直接使用IO0进行配置了。
#include "bflb_gpio.h"
#include "bflb_mtimer.h"
#include "board.h"
struct bflb_device_s *gpio;
#define gpio_test GPIO_PIN_0
int main(void)
{
board_init();
//获取gpio设备
gpio = bflb_device_get_by_name("gpio");
//配置io 0 为上拉 输出
bflb_gpio_init(gpio, gpio_test, GPIO_OUTPUT | GPIO_PULLUP);
while (1)
{
bflb_gpio_set(gpio, gpio_test); // 拉高
bflb_mtimer_delay_ms(100); // 延时100ms
bflb_gpio_reset(gpio, gpio_test); // 拉低
bflb_mtimer_delay_ms(100);
}
}
将上述代码编译烧录到小安派。接下来就使用rp2040做的逻辑分析仪来测量IO0的输出。
4. 使用逻辑分析仪验证
树莓派pico烧入逻辑分析仪固件,插入到电脑上。配置好plusview。(这个过程不详述。)
将pico的gnd和GP2分别和小安派的GND和I2C_SCL_TOP连接。
运行逻辑分析仪,就可以抓到如下的波形:
从波形中可以看到,电平变化的间隔正好是100ms和我们的程序中的是完全一致的。
至此,gpio功能我们就了解了。