[006] [STM32] GPIO模块锁定机制的bug

STM32
锁定寄存器
功能测试

本文为百问网&韦东山【物联网智能家居实战训练营】课程笔记

1 锁定寄存器

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

LCKR即为GPIO模块端口配置锁定寄存器,具体用法如下:

  • 用于锁定GPIO模块相应引脚的CRLCRH端口配置寄存器,一但锁定成功后,无法修改该引脚对应的端口配置寄存器;
  • 16为锁键LCKK,必须按:写1 -> 写0 -> 写1 -> 读0 -> 读1 的顺序写入,其中最后读1可以省略(可以判断是否锁定成功,成功则可以读出1),如果操作顺序出错则不能激活锁键;
  • LCKy[15:0]每位对应某GPIO端口的引脚号,只能在锁键激活之前(LCKK位=0)写入,写入1表示锁定成功;若在锁键激活后写入,即使写入的是1,也会被硬件置0。
  • 其余位(31:17)保留。

2 功能测试

uint8_t lock_gpio(GPIO_TypeDef* gpio_port, uint16_t gpio_pin)
{
    gpio_port->LCKR |= 1 << 16;		// LCKK写1
    gpio_port->LCKR = gpio_pin;     // LCKK写0 & 引脚对应的LCKy位写1
    gpio_port->LCKR |= 1 << 16;     // LCKK写1
    gpio_port->LCKR;                // 读LCKK   (此时读出值为0)
	
	return gpio_port->LCKR >> 16;   // 读LCKK   (此时读出值为1, 该操作可省略)
}
int main()
{
    lock_gpio(GPIOB, GPIO_PIN_0 | GPIO_PIN_8);

    GPIOB->CRL &= ~(0x0f << (0 * 4));
    GPIOB->CRL |= 0x03 << (0 * 4);

    GPIOB->CRH &= ~(0x0f << (0 * 4));
    GPIOB->CRH |= 0x03 << (0 * 4);
    
    while(1);
    return 0;
}

MDK仿真结果:
[006] [STM32] GPIO模块锁定机制的bug_第1张图片
CRL = 0x4444 4444表示复位后引脚处于浮空输入模式(01 00),说明PIN0锁定成功;CRH = 0x4444 4443说明高位引脚PIN8缺锁定失败,但LCK8却为1。

在此不妨假设锁定寄存器无法锁住CRH寄存器,下面开始验证:

int main()
{
    lock_gpio(GPIOB, 0xffff); // pin0~15
    
    GPIOB->CRL = 0x33333333;
    GPIOB->CRH = 0x33333333;

    while(1);
    return 0;
}

[006] [STM32] GPIO模块锁定机制的bug_第2张图片
猜想正确,LCKR无法锁住CRH寄存器。

END

你可能感兴趣的:(STM32,stm32,单片机,arm)