STMicroelectronics / STM32CubeH7

STM32Cube MCU Full Package for the STM32H7 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
https://www.st.com/en/embedded-software/stm32cubeh7.html
Other
495 stars 303 forks source link

STM32H7 RCC Driver Doesn't Support Changing HSIDIV When SYSCLK Using HSI #149

Closed paulr227 closed 3 years ago

paulr227 commented 3 years ago

According to RM0455 it should be possible to change HSIDIV when HSI is selected as the system clock, as long as HSI is not used as the PLL Source and a PLL enabled:

Note that the HSIDIV cannot be changed if the HSI is selected as reference clock for at least one enabled PLL (PLLxON bit set to 1). In that case the hardware does not update the HSIDIV with the new value. However it is possible to change the HSIDIV if the HSI is used directly as system clock.

However, the condition on the following line evaluates to true and __HAL_RCC_HSE_CONFIG() is then never called to update HSIDIV.

https://github.com/STMicroelectronics/STM32CubeH7/blob/ccb11556044540590ca6e45056e6b65cdca2deb2/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c#L482

E.g. if HSI_DIV4 is configured with CubeIDE's Clock Configuration (with PLLs off), CDCPRE=HPRE=DIV1, the following code is generated:

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_HSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

The HSIDIV configuration will remain at DIV1, AXI clock at 64 MHz but the Flash LATENCY will be set to 0 wait states (max AXI clock for 0 WS, VOS0 is 42 MHz), resulting in an invalid configuration and the MCU entering an invalid state.

RKOUSTM commented 3 years ago

Hi @paulr227,

Thank you for your contribution. In order to allow a better analysis of this problem, could you please give us the .ioc file that you are used to reproduce this issue. Thank you again for your contribution.

With regards,

paulr227 commented 3 years ago

Hi @RKOUSTM,

Please see attached. Let me know if you need anything else.

Regards OtpTest.ioc.zip

RKOUSTM commented 3 years ago

Hi @paulr227,

First of all, thank you for your reply. After investigation, this problem is related to the CubeIDE generation. Please find attached a generated template project for STM32H7A3 Nucleo board using STM32CubeMX v6.2.1.

OtpTest.ioc1.zip

I hope this generated template addresses your need. However, this public organization on GitHub is intended to promote co-development and issues posted here shall exclusively be related to the software published within the different repositories.

For any other issue (e.g. related to documentation, to hardware, to ecosystem, to user application, etc.), you shall address your questions to the ST Community. There you shall look for the adequate topic and submit your question or remark.

Please allow me to close this issue now. Thank you for your report.

With regards,

paulr227 commented 3 years ago

Hello @RKOUSTM,

Thanks for your response.

After investigation, this problem is related to the CubeIDE generation. Please find attached a generated template project for STM32H7A3 Nucleo board using STM32CubeMX v6.2.1.

Are you able to be more specific as to how this was resolved? The attached generated code still uses the default DIV1 for HSI (in main.c), which I don't believe was the problem, the problem was when DIV4 is selected for the HSI.

RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;

I see no changes in the attached RCC driver source to address this either.

Thanks.

RKOUSTM commented 3 years ago

Hi @paulr227,

We have detected a generation problem related to the system clock configuration using CubeIDE tools and not directly related to the firmware published in this repository. Indeed, we tried to reproduce the issue you described using STM32CubeMX, but we couldn't notice any problem. In fact, when the HSI is selected as the system clock, as long as the HSI is not used as a PLL source and a PLL is enabled, the SYSCLK can be varied up to 64Mhz :

According to the FLASH recommended number of wait states and programming delay table in the RM0455, you can get an idea about the flash latency equivalent for each rang of clock frequency.

I hope this answer addresses your need. Thank you again for your report. Do not hesitate in case you have other questions or feedback. We are looking forward to reading from you again.

With regards,

paulr227 commented 3 years ago

Hi @RKOUSTM,

Thanks for the response.

Ok, I understand the original issue better now, I suspect the driver probably shouldn't be evaluating the if condition on line 482 to true as the PLLs are disabled at the time (and explicitly disabled in "Clock Configuration", CSI seems to have been selected as the PLL source)?

if((temp_sysclksrc == RCC_CFGR_SWS_HSI) || ((temp_sysclksrc == RCC_CFGR_SWS_PLL1) && ((temp_pllckselr & RCC_PLLCKSELR_PLLSRC) == RCC_PLLCKSELR_PLLSRC_HSI)))

The generated code did correctly set the PLL state to None, so that looks OK.

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_DIV4; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

The condition on line 482 of the driver evaluates to true as it checks the current value of PLLSRC in PLLCKSELR which defaults to HSI at reset. Therefore the HSI configuration macro below is not applied, and the HSI continues to operate at the reset default, i.e. DIV1.

__HAL_RCC_HSI_CONFIG(RCC_OscInitStruct->HSIState);

As the HSI divider is still set to DIV1, then the code generated to configure the latency causes a problem as it should be using a latency of 1 (not 0) for 64 MHz.

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

So it looks to me as if there is still an issue? I'm unsure a change in the generated code alone without also a change in the driver code would resolve this. Note that the OtpTest.ioc1.zip you attached was configured for an HSI with DIV1, so I think that would not cause the issue to be observed.

I wonder if the check on line 482 of the driver should also check if any of the PLLs are actually enabled? RM0455 suggests its OK to change HSIDIV even if HSI is the PLL source, as long as no PLLs are enabled.

Note that the HSIDIV cannot be changed if the HSI is selected as reference clock for at least one enabled PLL (PLLxON bit set to 1). In that case the hardware does not update the HSIDIV with the new value. However it is possible to change the HSIDIV if the HSI is used directly as system clock.

Regards

paulr227 commented 3 years ago

Sorry, the reason line 482 evaluates to true is obviously the first condition:

if((temp_sysclksrc == RCC_CFGR_SWS_HSI) ||

However, I think the rest of the conclusion is valid (and is inline with what I originally reported). I.e. that the driver does not set HSI DIV4 as the macro __HAL_RCC_HSI_CONFIG is then not invoked. Consequently the flash latency of 0 is set but invalid as the HSI divider is still DIV1.

So I'm none the wiser how the code generation fix has resolved this...

Regards

paulr227 commented 3 years ago

Hi @RKOUSTM,

Sorry for the multiple responses on this. I cannot yet see 6.2.1 publicly released yet, so I've tried to import your OtpTest.ioc1.zip into my environment, avoiding any code re-generation, and modifying just the following two lines:

//  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;`

And

//  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)`

I see the same issue, i.e. RCC_HSI_DIV4 is not set in RCC_CR and the MCU gets into a bad state after setting the flash latency configuration. Are you able to confirm?

Regards

RKOUSTM commented 3 years ago

Hi @paulr227,

We tried to reproduce the issue you described with generated a project using the STM32CubeMX v6.2.1, but we couldn't notice the problem.

You can fined this CubeMX 6.2.1 version in ST.com site.

Thank you again for your contribution.

With regards,

paulr227 commented 3 years ago

Hi @RKOUSTM,

Sorry, my bad. I couldn't see v6.2.1 in the "Select Version" pull-down so assumed it wasn't publicly released yet. Only when I downloaded without selecting a version did I realise the downloaded version was v6.2.1.

Anyway, with v6.2.1 the steps are still the same, only 2 clock configuration changes to the default configuration for the NUCLEO board:

  1. From Board Selector choose NUCLEO-H7A3ZI-Q
  2. Initialise all peripherals with their default mode -> Yes
  3. Clock Configuration change HSI divider to DIV4 (16 MHz)
  4. Clock Configuration change SYSCLK source to HSI (16 MHz)
  5. Generate Code -> Toolchain STM32CubeIDE

Open CubeIDE project and download to the board and run, you'll find it crashes when setting the latency to zero. I.e. this is definitely still an issue with 6.2.1.

There are two elementary configuration changes from the standard NUCLEO project, no user code, i.e. 100% generated code. Struggling to see how your developers couldn't reproduce this from the description... no clarifications were requested either.

HSI_DIV4.zip with full generated project attached.

Please let me know if you still can't reproduce it.

Regards