STM32 problem record

1, The external crystal oscillator failed to start, resulting in abnormal serial port baud rate

Model: stm32f407
In the development process, due to the design problems of wiring and conditioning circuit, the external crystal oscillator will fail to start. In stm32, when the external crystal oscillator fails to start, the internal high-speed crystal oscillator will be started and the default clock configuration will be maintained.
Take hal library as an example. The specific code is in hal function_ RCC_ Implemented in clockconfig():
1. First, configure the internal crystal oscillator, and the default frequency division coefficient (HSI signals are directly provided to SYSCLK, all 16 frequency division): that is, the system clock is 16M and the peripheral clock is 1M
2. Start initializing the developer's real configuration, which has been stored in the handle RCC_ In clkrinittypedef, the first step is to wait for the external crystal oscillator to vibrate (prepare)
3. When ready, configure PLL, SYSCLK signal source and peripheral clock allocation coefficient
4. Finally, update some data (information)
In these steps, if one of the steps fails, an error will be returned and no further execution will be carried out. If the internal clock initialization fails, a hardware error interrupt will be applied directly. If the external crystal oscillator fails to start, the default configuration (internal HSI, 16 frequency division) will be maintained

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
{
...
  /*-------------------------- HCLK Configuration --------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
  {
    /* Set the highest APBx dividers in order to ensure that we do not go through
       a non-spec phase whatever we decrease or increase HCLK. */
    if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
    {
      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);
    }

    if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
    {
      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, (RCC_HCLK_DIV16 << 3));
    }

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

  /*------------------------- SYSCLK Configuration ---------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
  {
    assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));

    /* HSE is selected as System Clock Source */
    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
    {
      /* Check the HSE ready flag */
      if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
      {
        return HAL_ERROR;
      }
    }
    /* PLL is selected as System Clock Source */
    else if((RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)   ||
            (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLRCLK))
    {
      /* Check the PLL ready flag */
      if(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
      {
        return HAL_ERROR;
      }
    }
    /* HSI is selected as System Clock Source */
    else
    {
      /* Check the HSI ready flag */
      if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
      {
        return HAL_ERROR;
      }
    }

    __HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);

    /* 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;
      }
    }
  }
 /*-------------------------- 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);
  }

  /*-------------------------- 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));
  }

 ...
 }

So how does the failure of external crystal oscillator affect the serial baud rate? The original baud rate of the serial port is configured as 115200 and the corresponding clock is 0.1M. At first, during communication, it was found that the data transmission often timed out, resulting in abnormal system tasks. After checking the amount of data, use an oscilloscope to observe that the output waveform is inconsistent with the configuration, and it is determined that the baud rate is abnormal. Then, after troubleshooting the hardware circuit problem, start troubleshooting the clock problem of the main control chip through the following function:
1,HAL_RCC_GETSysClockFreq(); // Get system clock
2,HAL_RCC_GetPCLK2Freq(); // Obtain the high-speed peripheral bus clock (serial port 1 is mounted here)

The data obtained are consistent with the previous analysis, with a main frequency of 16M and a peripheral clock of 1M. According to the calculated formula baud = Fclk/8*(2-OVER8)USARTDIV
1M/82115200=USARTDIV=0.54 (16 times oversampling)
Then register BRR should load 0x09 ((0 < < 4) + 0.5416)
Check the BRR register data. It is indeed 0x09

Since the baud rate is configured correctly, why is it wrong? I initially suspected that the baud rate was too high and decreased. I found that the baud rate did become normal, but I didn't quite understand it. It is reasonable that the 1M clock can drive the baud rate of 115200. After some thinking, I attributed the reason to the oversampling configuration. In order to ensure the reliability of data, the general serial port equipment will be oversampling configured, Since the previous configuration was 16 times oversampling, the main control chip needs a clock of about 1.6M to complete. However, the current clock configuration does not meet the requirements, resulting in abnormal baud rate.

After knowing the reason, several modifications can be made to correct the baud rate:
1. The optimal solution is to start the external crystal oscillator (check the crystal oscillator and peripheral circuit).
2. Temporary debugging can enable the internal high-speed crystal oscillator to configure a high clock.
3. Those who are too lazy to configure can use RCC in the above code_ HCLK_ Div16 changed to RCC_HCLK_DIV1, that is, do not allocate and set the peripheral clock to 16M.
4. Second, you can reduce the baud rate or use 8x oversampling.

Keywords: Embedded system stm32

Added by heyjohnlim on Thu, 16 Dec 2021 22:39:32 +0200