STM32G474CBT6之HAL_RCC_ClockConfig()问题?

STM32G474CBT6之HAL_RCC_ClockConfig()问题?

很多人在用HAL库时,都用到了寄存器,特别是在数字电源案例中。我也在想,有了标准库,为什么要搞HAL库?HAL库降低了入门的门槛,但在实际应用中,问题也多。最近在阅读HAL_RCC_ClockConfig()函数时,我发现一个问题,问了群里的研发人员,大家也认为是一个bug,但是这个bug很难表现出来,因为后面的程序将前面的错误给修改了,但对于局部来说,是一个bug

问题如下:
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_HCLK_DIV16);
修改对象是“RCC_CFGR_PPRE2

 

HAL库程序如下:

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)

{

  uint32_t tickstart;

  uint32_t pllfreq;

  uint32_t hpre = RCC_SYSCLK_DIV1;

  /* Check Null pointer */

  if (RCC_ClkInitStruct == NULL)

  {

    return HAL_ERROR;

  }

  /* Check the parameters */

  assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));

  assert_param(IS_FLASH_LATENCY(FLatency));

  /* To correctly read data from FLASH memory, the number of wait states (LATENCY)

    must be correctly programmed according to the frequency of the CPU clock

    (HCLK) and the supply voltage of the device. */

  /* Increasing the number of wait states because of higher CPU frequency */

  if (FLatency > __HAL_FLASH_GET_LATENCY())

  {//读取FLASH->ACR寄存器的bit3:0(LATENCY[3:0])

    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */

    __HAL_FLASH_SET_LATENCY(FLatency);

         //设置FLASH->ACR寄存器的bit3:0(LATENCY[3:0]),令LATENCY[3:0]=FLatency

    /* Check that the new number of wait states is taken into account to access the Flash

    memory by reading the FLASH_ACR register */

    if (__HAL_FLASH_GET_LATENCY() != FLatency)

    {

      return HAL_ERROR;

    }

  }

  /*--------SYSCLK系统时钟配置(SYSCLK Configuration)--------------*/

  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)

  {

    assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));

    /*使用PLL作为系统时钟源,PLL is selected as System Clock Source */

    if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)

    {

      /* Check the PLL ready flag */

      if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)

      {//RCC->CR寄存器的bit25(PLLRDY),PLLRDY=1表示PLL时钟已经就绪

        return HAL_ERROR;

      }

      /* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */

      /* Compute target PLL output frequency */

      pllfreq = RCC_GetSysClockFreqFromPLLSource();//读取系统时钟频率为85MHz

      /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */

                            //在超过80MHz之前,需要这个中间步骤将HCLK设置为2分频

      if(pllfreq > 80000000U)//如果系统时钟频率大于80MHz

      {

        if (((READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)) ||

            (((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) &&

              (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1))))

        {

          MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);

/*修改RCC->CFGR寄存器bit7:4(HPRE[3:0]),HPRE[3:0]=1000b,设置AHB分频器值为2分频;AHB时钟为系统时钟的2分频,SYSCLK divided by 2HCLK时钟频率为系统时钟的2分频,后面会再次对它进行配置,这里是个中间步骤。*/

          hpre = RCC_SYSCLK_DIV2;

//记录,后面以此为依据来修改;但是本次配置已经指定了"AHB时钟(HCLK)的分频值"

        }

      }

    }

    else

    {

      /* HSE is selected as System Clock Source */

      if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)

      {

        /* Check the HSE ready flag */

        if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)

        {

          return HAL_ERROR;

        }

      }

      /* HSI is selected as System Clock Source */

      else

      {

        /* Check the HSI ready flag */

        if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)

        {

          return HAL_ERROR;

        }

      }

      /* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */

      pllfreq = HAL_RCC_GetSysClockFreq();

    /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */

      if(pllfreq > 80000000U)

      {

        MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);

        hpre = RCC_SYSCLK_DIV2;

      }

    }

    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);

//修改RCC->CFGR寄存器bit1:0(SW[1:0]),SW[1:0]=11bPLL被选择为系统时钟

    /* Get Start Tick*/

    tickstart = HAL_GetTick();

    while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))

    {

      if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)

      {

        return HAL_TIMEOUT;

      }

    }

  }

  /*-------HCLK时钟配置,HCLK Configuration --------------*/

  if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)

  {

    /* Set the highest APB divider in order to ensure that we do not go through

       a non-spec phase whatever we decrease or increase HCLK. */

/*设置最高的APB分配器,以确保我们不会经历一个非规范的阶段,无论我们如何减少或增加HCLK*/

    if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)

    {

      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);

/*修改RCC->CFGR寄存器bit10:8(PPRE1[2:0]),PPRE1[2:0]=111bAPB1分频器值为16; APB1时钟,PCLK1时钟为HCLK divided by 16,后面会对它进行修改,这里是一个中间步骤;*/

    }

    if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)

    {

      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_HCLK_DIV16);

/*修改RCC->CFGR寄存器bit13:11(PPRE2[2:0]),PPRE2[2:0]=111bAPB2分频器值为16;APB2时钟,PCLK2时钟为HCLK divided by 16,后面会对它进行修改,这里是一个中间步骤;*/

//这个“HAL库”是不是错了?还是有意为之??

    }

    /* Set the new HCLK clock divider */

    assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));

    MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);

/*修改RCC->CFGR寄存器bit7:4(HPRE[3:0]),HPRE[3:0]=0xxxbAHB分频器值为1HCLKSYSCLK not divided;还记得前面有一个中间步骤吗?这里再次配置HCLK时钟分频器。*/

  }

  else

  {

    /* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */

    if(hpre == RCC_SYSCLK_DIV2)

    {

      MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1);

    }

  }

  /* Decreasing the number of wait states because of lower CPU frequency */

  if (FLatency < __HAL_FLASH_GET_LATENCY())

  {//读取FLASH->ACR寄存器的bit3:0(LATENCY[3:0])

    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */

    __HAL_FLASH_SET_LATENCY(FLatency);

/*设置FLASH->ACR寄存器的bit3:0(LATENCY[3:0]),令LATENCY[3:0]=FLatency*/

    /* Check that the new number of wait states is taken into account to access the Flash

    memory by polling the FLASH_ACR register */

    tickstart = HAL_GetTick();

    while (__HAL_FLASH_GET_LATENCY() != FLatency)

    {

      if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)

      {

        return HAL_TIMEOUT;

      }

    }

  }

  /*--------PCLK1时钟配置,PCLK1 Configuration ---------*/

  if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)

  {

    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));

    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);

/*修改RCC->CFGR寄存器bit10:8(PPRE1[2:0]),PPRE1[2:0]=0xxbAPB1分频器值为1APB1时钟,PCLK1时钟为HCLK divided by 1;记得前面对它配置过一次,用的是16分频,但那只是一个中间步骤,不是最终的配置;*/

  }

  /*--------PCLK2时钟配置,PCLK2 Configuration ----------*/

  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)

  {

    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));

    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));

/*修改RCC->CFGR寄存器bit13:11(PPRE2[2:0]),PPRE2[2:0]=0xxxbAPB2分频器值为1APB2时钟,PCLK2时钟为HCLK divided by 1;记得前面对它配置过一次,用的是16分频,但那只是一个中间步骤,不是最终的配置;*/

  }

  /* Update the SystemCoreClock global variable */

  SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU);

  //读取系统时钟频率为85MHz

  /* Configure the source of time base considering new system clocks settings*/

  return HAL_InitTick(TICK_INT_PRIORITY);

}

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值