硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4302|回复: 7
收起左侧

[客户分享] STM32Cube_FW_F1_V1.7.0似乎存在bug!

[复制链接]

4

主题

24

回帖

36

积分

新手上路

积分
36
发表于 2019-3-29 13:47:31 | 显示全部楼层 |阅读模式
本帖最后由 longge 于 2019-3-29 13:47 编辑

ST的官方工具STM32CubeMX是目前开发STM32的常用工具,之前在STM32F4和STM32L0使用过,感觉还可以。我用的都是LL库,不是HAL库系列。因为LL库比HAL效率更高,接近之前的标准库,当然是封装的层少,个人感觉。
今天手里有块STM32F103C8的开发板,用STM32CubeMX开发程序中,发现本来设定的LED灯都是常闭的,可是程序跑起来后,发现默认都是常亮的。自己一度怀疑是程序写的有问题或是J-link有问题。
后来,调试发现是ST官方的STM32Cube_FW_F1_V1.7.0存在bug。调试中发现通过设置GPIO port bit set/reset register (GPIOx_BSRR) (x = A..I/J/K)来设置GPIO port output data register (GPIOx_ODR) (x = A..I/J/K)寄存器,引脚对应的寄存器位正常被设置,
但是在随后的LL_GPIO_Init(GPIOA, &GPIO_InitStruct)函数中设置对应引脚上下拉时,对应的GPIOx_ODR (x = A..I/J/K)寄存器也会被设置。还有,我都是通过STM32CubeMX里边下载官方库,应该是最新的SMT32F1系列的HAL库,STM32F1版本:STM32Cube_FW_F1_V1.7.0,STM32F4版本:STM32Cube_FW_F4_V1.24.0,STM32L0版本:STM32Cube_FW_L0_V1.11.2。

以下是STM32CubeMX自动生成的GPIO初始化代码:官方生成的初始化代码都是先设置对应的引脚电平,然后再初始化设置引脚的模式,速率等。如果先初始化引脚的模式等,再设置引脚的电平不会出现这个问题。

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* GPIO Ports Clock Enable */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
    /**/
    LL_GPIO_ResetOutputPin(GPIOA, LED0_Pin | POWER_MC20_Pin);
    LL_GPIO_SetOutputPin(GPIOA, LED0_Pin);
    LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_0);     //设置对应的引脚默认为高电平,但是经过以下的LL_GPIO_Init(GPIOA, &GPIO_InitStruct)后,GPIOx_ODR会被设置为低电平。我设置的是GPIOA0引脚,换为GPIOB0和GPIOB1引脚还是存在这个问题。
    /**/
    LL_GPIO_SetOutputPin(GPIOB, LED1_Pin | LED2_Pin);
    /**/
    GPIO_InitStruct.Pin = LED0_Pin | POWER_MC20_Pin;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//    LL_GPIO_SetOutputPin(GPIOA, LED0_Pin);
    /**/
    GPIO_InitStruct.Pin = LED1_Pin | LED2_Pin;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
//    LL_GPIO_SetOutputPin(GPIOB, LED1_Pin | LED2_Pin);
}
注释部分是我手动添加的,默认软件是先设置对应的引脚电平,然后在初始化的。可是,由于函数LL_GPIO_Init(GPIOA, &GPIO_InitStruct)中设置上下拉部分的作用会导致之前设置的高电平被清零掉。要想真正的起作用,必须在函数LL_GPIO_Init(GPIOA, &GPIO_InitStruct)后重新设置对应引脚的电平。
以下是官方HAL库中stm32f1xx_ll_gpio.c文件中函数LL_GPIO_Init()代码,加注释的地方应该存在bug。
/**
  * @brief  Initialize GPIO registers according to the specified parameters in GPIO_InitStruct.
  * @param  GPIOx GPIO Port
  * @param  GPIO_InitStruct: pointer to a @ref LL_GPIO_InitTypeDef structure
  *         that contains the configuration information for the specified GPIO peripheral.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: GPIO registers are initialized according to GPIO_InitStruct content
  *          - ERROR:   Not applicable
  */
ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
{
  uint32_t pinmask;
  uint32_t pinpos;
  uint32_t currentpin;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
  assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));

  /* ------------------------- Configure the port pins ---------------- */
  /* Initialize  pinpos on first pin set */

  pinmask = ((GPIO_InitStruct->Pin) << GPIO_PIN_MASK_POS) >> GPIO_PIN_NB;
  pinpos = POSITION_VAL(pinmask);

  /* Configure the port pins */
  while ((pinmask  >> pinpos) != 0U)
  {
    /* skip if bit is not set */
    if ((pinmask & (1U << pinpos)) != 0U)
    {
      /* Get current io position */
      if (pinpos < GPIO_PIN_MASK_POS)
      {
        currentpin = (0x00000101U << pinpos);
      }
      else
      {
        currentpin = ((0x00010001U << (pinpos - GPIO_PIN_MASK_POS)) | 0x04000000U);
      }

      /* Check Pin Mode and Pin Pull parameters */
      assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
      assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));

      /* Pin Mode configuration */
      LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);

      /* Pull-up Pull-down resistor configuration*/
      LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);   //设置上下拉部分代码,就是这部分导致之前设置的GPIOx_ODR寄存器对应位会被清零掉。

      if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
      {
        /* Check speed and Output mode parameters */
        assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));
        assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));

        /* Speed mode configuration */
        LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed);

        /* Output mode configuration*/
        LL_GPIO_SetPinOutputType(GPIOx, currentpin, GPIO_InitStruct->OutputType);
      }
    }
    pinpos++;
  }
  return (SUCCESS);
}

后来,测试STM32L0和STM32F4的LL库这部分,没有存在问题。看芯片的技术文档,发现:STM32L0和F4系列有专门的上下拉设置寄存器GPIO port pull-up/pull-down register (GPIOx_PUPDR),而STM32F1系列应该是没有这个配置的寄存器(也不是很确定,我看的RM0008 技术手册,对应 STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx advanced ARM&#174;-based 32-bit MCUs,里面是没有提到有上下拉寄存器),所以同样的函数LL_GPIO_Init()代码处理是不一样的,在F4和L0系列中,LL_GPIO_Init()函数没有问题,在F1中存在这个问题。

以下是F1系列,F4系列,L0系列中设置上下拉函数LL_GPIO_SetPinPull()的代码:

F1系列:个人感觉既然F1系列中没有上下拉设置寄存器,这个函数显得有些鸡肋,虽然显得HAL库中接口统一了。

__STATIC_INLINE void LL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
{
  MODIFY_REG(GPIOx->ODR, (Pin >> GPIO_PIN_MASK_POS), Pull << (POSITION_VAL(Pin >> GPIO_PIN_MASK_POS)));
}

F4系列:

__STATIC_INLINE void LL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
{
  MODIFY_REG(GPIOx->PUPDR, (GPIO_PUPDR_PUPDR0 << (POSITION_VAL(Pin) * 2U)), (Pull << (POSITION_VAL(Pin) * 2U)));
}

L0系列:

__STATIC_INLINE void LL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
{
  MODIFY_REG(GPIOx->PUPDR, ((Pin * Pin) * GPIO_PUPDR_PUPD0), ((Pin * Pin) * Pull));
}



希望大家测试下,是否真的有这个问题。还有,以上都是个人意见,如有不妥之处,希望大家见谅。



评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 赞一个!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2019-3-29 14:08:19 | 显示全部楼层
非常感谢楼主分享。
回复

使用道具 举报

4

主题

24

回帖

36

积分

新手上路

积分
36
 楼主| 发表于 2019-3-29 14:39:50 | 显示全部楼层
eric2013 发表于 2019-3-29 14:08
非常感谢楼主分享。

硬汉大哥过奖了,只是想大家一起看下是不是有这个问题。
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2020-5-25 00:37:25 | 显示全部楼层
新版本1.80问题还是在的,我也碰到了,明明设为起动是高电平的,最后还是低电平启动的,最后换回HAL库了。
而且我还遇到更为奇怪的事,因为我连的是蜂鸣器,所以一开机就响的很,开始用寄存器自己初始化也搞不定,最后换了板子,结果好了,板子上能换的都换了也还是开机响,最后换了MCU才解决问题,MCU其它管脚表现正常,就这个GPIOB12有问题。同一天竟然软硬件同时考验我。
回复

使用道具 举报

73

主题

1200

回帖

1419

积分

至尊会员

积分
1419
发表于 2020-5-25 11:07:41 | 显示全部楼层
我就是1.6.1,不更新
回复

使用道具 举报

335

主题

2037

回帖

3047

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3047
发表于 2020-5-25 16:42:04 | 显示全部楼层
CubeMx生成的代码在这一点确实奇怪,它是先设置管脚电平,再设置管脚的模式。 不放心的话,自己最后再设置一遍。
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2022-1-23 18:27:19 | 显示全部楼层
wdliming 发表于 2020-5-25 11:07
我就是1.6.1,不更新

能否分享一下1.6.1,190805562@qq.com
网上下载不了了,十分感谢
回复

使用道具 举报

210

主题

1045

回帖

1685

积分

至尊会员

More we do, more we can do.

积分
1685
发表于 2022-1-25 09:45:47 | 显示全部楼层
既然有人回了老帖,我就顺便看了下,LL那版确实有坑,原因是F1只输入时支持上下拉,V1.8.4问题已经修正,加了模式判断。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 18:24 , Processed in 0.240089 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表