一、目的
在之前的博文中我们主要介绍了不同系统不同开发编译调试环境的配置和操作(命令行方式、Visual Studio Code、Segger Embedded Studio for RISC-V),以帮助大家准备好学习环境为目的,但是未涉及到芯片本身以及外设的讲解。
从本篇开始我们将逐一介绍一些常用的芯片外设模块(GPIO、串口、SPI、网口等等),首当其中的就是最基础的GPIO操作(设置IO方向,进行IO读写操作)。
二、介绍
在先楫官网的文档中对GPIO做了相当详细的描述,大家可以参考阅读,下文会针对官网文档进行一个总结性的说明。
先楫半导体http://www.hpmicro.com/resources/resources.html
GPIO在系统框图中的位置
HPM6750芯片将整个系统划分为三个电源域(系统电源域、电源管理域、电池备份域)。
1.IO控制器说明
IO控制器 | 说明 |
---|---|
IOC | 通用IO控制器 位于系统电源域 管理PA(0-31)、PB(0-31)、PC(0-31)、PD(0-31)、PE(0-31)、PF(0-10) |
PIOC | 电源管理域IO控制器,功能和通用IOC一致 管理PY(0-11) |
BIOC | 电池备份域IO控制器,功能和通用IOC一致,管理PZ(0-11) |
PIOC和BIOC可以把电源管理域IO(PY)和电池备份域IO(PZ)中的一个或者多个IO映射到系统电源域,之后这些IO就可以由IOC控制。这个我们在以后章节介绍UART时讲解。
IO控制器主要控制这些参数:
- 外设复用功能映射
- 输出回送控制(loopback)
- 模拟功能配置
- 电压模式控制
- 开漏设置
- 施密特触发器
- 上下拉配置
- 驱动能力配置
每个IOC控制的pin都有两个寄存器参数,分别为叫做FUNC_CTL、PAD_CTL,具体的寄存器字段信息如下:
寄存器名称 | 字段 | 功能 |
---|---|---|
FUNC_CTL | ALT_SELECT[4:0] | 外设复用功能映射选择,具体每个IO的映射关系从芯片手册或者SDK源码中可以查阅 |
ANALOG[8:8] | 引脚切换至模拟输入输出功能开关 | |
LOOPBACK[16:16] | 输出回送开关 | |
PAD_CTL | DS[2:0] | 驱动强度选择 |
PE[4:4] | 内部上下拉功能开关 | |
PS[11:11] | 内部上下拉电阻选择 | |
SMT[12:12] | 输入施密特触发器使能, 此位只对高速引脚可用 | |
OD[13:13] | 开漏输出开关 | |
MS[14:14] | 引脚供电电压选择, 此位只对高速引脚可用 |
关于这些描述可以查看官方文档中更加详细的描述,并且在进行在线调试时我们也可以看到这些信息。
在SDK中我们可以查看每个IO的复用设置信息,例如下图是PB18这个引脚的复用选项。
看过我之前文章的小伙伴肯定也看到过下图中调试窗口中各个外设寄存器信息。
有了上面的基本知识后,我们再来看下hpm-sdk中关于IO控制器的定义:
HPM_IOC/HPM_PIOC/HPM_BIOC都是IOC_Type类型的结构体指针,IOC_Type结构体内部又是PAD结构体数组,每个数组元素则对应一个IO引脚,每个引脚都有FUNC_CTL和PAD_CTL寄存器。
从上图可以看到PB.18引脚对应于IOC_Type中的第32+18=50个引脚,即PAD[50]。
2.GPIO控制说明
GPIO控制器包括GPIO0/1、FGPIO0/1、PGPIO、BGPIO,其主要功能:
- 配置IO作为输入或者输出
- 读取IO的输入状态
- 设置IO的输出
- 原子化操作设置IO输出高、低、翻转
其中GPIO0/1,PGIO,BGPIO 支持配置 GPIO 中断,FGPIO0 和 FGPIO1 不支持生成中断。
下图是各个GPIO对应的地址信息:
上图定义了GPIO_Type结构体类型,其中包括DI(输入寄存器)、DO(输出寄存器)、OE(输入输出方向寄存器)等等。注意DI/DO/OE等都是结构体数组,分别对应着PA/PB/PC等。
DO结构体数组中又定义了VALUE、SET、CLEAR、TOGGLE寄存器,每个寄存器都是32位,每一个bit代表一个引脚。
关于VALUE/SET/CLEAR/TOGGLE寄存器描述如下:
3.读取引脚输入高低电平
/**
* @brief Read target pin level
*
* @param ptr GPIO base address
* @param port Port index
* @param pin Pin index
*
* @return Pin status mask
*/
static inline uint8_t gpio_read_pin(GPIO_Type *ptr, uint32_t port, uint8_t pin)
{
return (ptr->DI[port].VALUE & (1 << pin)) >> pin;
}
假如我们使用GPIO0读取PB.18的值,应该这样调用
uint8_t val = gpio_read_pin(HPM_GPIO0, GPIO_DI_GPIOB, 18);
三、实战
通过上面的介绍大家应该对GPIO有了一个基本印象,下面我们使用代码调试功能帮助大家加深理解。
cd ~/workspace/work/hpm/hello_world
code .
定位到board_turnoff_rgb_led函数,我们查看PB18引脚的FUNC_CTL默认值为0x0;PAD_CTL默认值为0x1010。
在执行过HPM_IOC->PAD[IOC_PAD_PB18].PAD_CTL = pad_ctl;这行代码后PAD_CTL变成了0x810。
自此GPIO的基本知识点就讲解完毕,大家对着官方文档和调试器调试代码可以进一步加深理解。