Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

STM32F401RCTx SPI and I2C clock running at double frequency, when using external XTAL. #2661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wltue opened this issue Feb 27, 2025 · 0 comments

Comments

@wltue
Copy link

wltue commented Feb 27, 2025

STM32F401RCTx SPI and I2C clock running at double frequency, when using external XTAL.

Problem description:
When using an external XTAL with the described setup below, generating the clock setup code with STM32CubeIDE, importing the ‘SystemClock_Config’’ code , the clock frequency of the I2C and the SPI will run at double the frequency requested or double speed at default settings.

Hardware description:
a custom board using a STM32F401RCTx with a 16mhz XTAL.
All measurements done with: MSOX3024G oscilloscope.
The problem has been tested on multiple exactly the same boards.
The XTAL frequency has been verified with the Oscilloscope.

The test examples in this issue report used on device:

STM32CubeProgrammer:
SN : 389A35833432
Device ID : 0x0423

Arduino:
USB speed : Full Speed (12MBit/s)
Manuf. ID : STMicroelectronics
Product ID : STM32 BOOTLOADER
SN : 389A35833432
DFU protocol: 1.1
Board : --
Device ID : 0x0423
Device name : STM32F401xB/C
Flash size : 256 KBytes (default)
Device type : MCU
Revision ID : --
Device CPU : Cortex-M4

Software used during these tests:
STM32CubeIDE 1.17.0 Build: 23558_20241125_2245 (UTC) (For generating the SystemClock_Config)

STM32CubeProgrammer v2.16.0 (required by Arduino IDE)

Arduino IDE 2.3.2
ArduinoSTM32duino library v2.8.1 (also tested)
ArduinoSTM32duino library v2.9.0
Flashing in DFU Mode.

Arduino IDE Board Settings:
Board: “Generic STM32F4 series”
Port: “COM88”
Debug symbols and core logs: ”None”
Optimize: “Smallest (-Os default)”
Board part number: “Generic F401RCTx”
C Runtime Library: “Newlib Nano (default)”
Upload method: “STM32CubeProgrammer (DFU)”
USB support (if available): “CDC (generic ‘Serial’supersede U(S)ART)”
U(S)ART support: “Disabled (no Serial support)”
USB speed (if available): “Low/Full Speed”

Code and test procedure description:
The C code included int this report has been used to test and verify the problem. The code will be modified for each testing step and uploaded to the target.
When the function ‘SystemClock_Config’ in the ‘STM32F401RCTx_XTALvsI2C.ino” code has been renamed and excluded for the Arduino environment, the STM32F401RCTx runs on the internal RC and the I2C clock is correct at 100khz.
When the function ‘SystemClock_Config’ in the ‘STM32F401RCTx_XTALvsI2C.ino” code has been enabled but the function ‘SystemClock_Config_RCC_HCLK_DIV4()’ has been disabled, the I2C clock is measured at 200khz.
When the function ‘SystemClock_Config’ in the ‘STM32F401RCTx_XTALvsI2C.ino” code has been enabled and the function ‘SystemClock_Config_RCC_HCLK_DIV4()’ has also been enabled, the I2C clock is measured at 100khz and so is correct. This can be used for now as a workaround, pending the final bug solution.
When the function ‘SystemClock_Config’ in the ‘STM32F401RCTx_XTALvsI2C.ino” code has been enabled, the function ‘SystemClock_Config_RCC_HCLK_DIV4()’ has also been enabled and the MCO1 function code in setup has also been enabled, the PA8 output measures 21Mhz with the oscilloscope.
The function ‘SystemClock_Config_RCC_HCLK_DIV4()’ is the same code as ‘SystemClock_Config’ but with the modification of ‘RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4’ instead of 2.
Conclusion:
Hard to tell for a beginner in STM32 with Arduino environment. But it seems in code ‘i2c_computeTiming(uint32_t clkSrcFreq, uint32_t i2c_speed) ‘ within file ‘Arduino_Core_STM32/libraries/Wire/src/utility/twi.c’, the calculation of the APB1CLKDivider versus the Arduino I2C and SPI code has an error.

Thank you for reading.

`
/*
STM32F401RCTx 16mhz XTAL testing vs I2C clock
*/

#include <Wire.h>

TwoWire Wire1(PB7, PB6);

/* system clock STM32F401RCT6 with external 16Mhz XTAL */

void SystemClock_Config(void)
{
/*
GPIO_InitTypeDef GPIO_InitStruct = {};

// GPIO Ports Clock Enable
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

// Configure GPIO pin : PA8
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
*/

RCC_OscInitTypeDef RCC_OscInitStruct = {};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

__HAL_RCC_TIM10_CLK_ENABLE();

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    /
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 168;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // org
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}

// MCO1 op pin PA8
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_4);
}

/* system clock STM32F401RCT6 with external 16Mhz XTAL, but with I2C and SPI clock correction */

void SystemClock_Config_RCC_HCLK_DIV4(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

__HAL_RCC_TIM10_CLK_ENABLE();

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    /
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 168;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // I2C and SPI clocks to high
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}

// MCO1 op pin PA8
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_4);
}

void setup(void)
{
delay(3000);

// Enable MCO1 on pin PA8 -> 21Mhz

if (false)
{

HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_4);

GPIO_InitTypeDef GPIO_InitStruct = {};

// GPIO Ports Clock Enable
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

// Configure GPIO pin : PA8
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

// Led
pinMode(PC13, OUTPUT);
digitalWrite(PC13, LOW);

Serial.begin(115200);

delay(1000);

Serial.println("Start");

// I2C1

Wire1.begin();
// Wire1.setClock(100000);

// Redo Clock settings but adapt the I2C and SPI clock to correct values
if (true)
{
SystemClock_Config_RCC_HCLK_DIV4();
}
}

void loop(void)
{
// I2C1

Wire1.beginTransmission(0x71);
Wire1.write('v'); // not sens no ack
Wire1.endTransmission();

delay(500);

Serial.println("Turn");

// Toggle LED
digitalWrite(PC13, !digitalRead(PC13));
}

`

@stm32duino stm32duino locked and limited conversation to collaborators Feb 27, 2025
@fpistm fpistm converted this issue into discussion #2662 Feb 27, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant