概述
最近做SDK的BSP驱动。之前使用STM32CubeMX进行开发,设计GPIO的初始化接口包括了mode、pull两个参数。 现在对接另一款国产芯片,芯片驱动仅支持标准库,在GPIO的初始化结构体中没有pull成员,且mode也不完全相同。那么该如何处理这两个参数呢?
HAL库
先看下STM32L152CCTx的工程,GPIO的初始化函数中对于pull的处理:
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
temp = GPIOx->PUPDR;
CLEAR_BIT(temp, GPIO_PUPDR_PUPDR0 << (position * 2));
SET_BIT(temp, (GPIO_Init->Pull) << (position * 2));
GPIOx->PUPDR = temp;
}
也就是操作PUPDR寄存器,查看手册定义如下: 而支持的mode如下:
#define GPIO_MODE_INPUT (0x00000000U)
#define GPIO_MODE_OUTPUT_PP (0x00000001U)
#define GPIO_MODE_OUTPUT_OD (0x00000011U)
#define GPIO_MODE_AF_PP (0x00000002U)
#define GPIO_MODE_AF_OD (0x00000012U)
#define GPIO_MODE_ANALOG (0x00000003U)
标准库
现在看下标准库时如何初始化的。标准库直接参考STM32F103的工程,GPIO初始化函数的主要代码如下:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
tmpreg |= (currentmode << pos);
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
}
- 获取模式的低四位,得到mode。若为输出,则一并设置 speed;
- 根据上拉还是下拉,管脚输出对应电平。
从代码可以看出,只有输入才会有上下拉。而支持的mode如下:
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
与HAL库相比,多了GPIO_Mode_IPD 和GPIO_Mode_IPU 。也就是HAL库需要设置为输入模式,再单独设置上拉、下拉、浮空,而标准库直接定义了上拉输入模式、下拉输入模式和浮空输入模式。
另外,每个pin的模式由4bit控制,为什么枚举采用8bit呢? 这一点从代码中也可以看出来,高四位的0x1表示输出。
再看HAL库
查看STM32F103参考手册,也并没有PUPDR寄存器,应该是不同内核的原因。 用STM32CubeMX生成一个STM32F103的HAL库版本,查看下HAL库是如何处理的。生成后直接定位到HAL_GPIO_Init 函数: 可以看到同样是对寄存器的4bit进行设置。展开switch,可以看到对Pull的处理,也就是先判断mode。如果为输入,则继续判断pull,最终还是归纳到标准库支持的8个mode:
到这里,SDK该如何处理mode和pull参数也就清晰了。
|