Skip to content

HAL_RCCEx_GetPeriphCLKFreq() uses nonexistent PLLI2SM field on STM32F411 / STM32F401, breaks I²S initialization #198

@joeyla

Description

@joeyla

Description

Package: STM32CubeF4
Version: v1.28.3 (and at least since v1.26.0)
Device(s) affected: STM32F411xE, STM32F401xD/E (confirmed on STM32F411CEU6 “Black Pill”)
File: stm32f4xx_hal_rcc_ex.c
Function: HAL_RCCEx_GetPeriphCLKFreq()

🧩 Summary

The HAL currently assumes that RCC_PLLI2SCFGR contains a PLLI2SM divider field for STM32F411.
That field does not exist on STM32F411/F401 devices — they share the main PLLM divider in RCC_PLLCFGR.

As a result, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S) divides by zero, returning 0 Hz for the I²S clock.
This makes HAL_I2S_Init() fail with error code HAL_I2S_ERROR_PRESCALER (0x10) and often leads to a HardFault if not handled.

🧪 How to Reproduce

Create a CubeMX project for STM32F411CEU6 (Black Pill).

Configure:

HSE = 25 MHz

PLLM = 25, PLLN = 336, PLLP = 4

PLLI2SN = 192, PLLI2SR = 2

Enable I²S1 in Half-Duplex Master Receive mode.

Call:

MX_I2S1_Init();

Observe:

HAL_I2S_Init() returns HAL_ERROR

hi2s1.ErrorCode = 0x00000010

HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S) returns 0 Hz

🧮 Root Cause

In stm32f4xx_hal_rcc_ex.c, around line 1410 (CubeF4 v1.28.3):

#if defined(STM32F411xE)
vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
#else
...
#endif

👉 The mask RCC_PLLI2SCFGR_PLLI2SM does not exist on STM32F411/401.
These MCUs only implement PLLM in RCC->PLLCFGR, shared between PLL and PLLI2S.
Therefore, the denominator becomes zero, and the computed I²S frequency is invalid.

✅ Proposed Fix

Replace the #if defined(STM32F411xE) section with:

/* Correct for STM32F411/401 family: use shared PLLM divider */
if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
{
vcoinput = HSE_VALUE / (RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
}
else
{
vcoinput = HSI_VALUE / (RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
}

vcooutput = vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U);
frequency = vcooutput / ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U);

🧠 Expected Result

HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S) correctly returns 96 MHz
(for PLLM=25, PLLI2SN=192, PLLI2SR=2, HSE=25 MHz),
and HAL_I2S_Init() completes successfully.

✅ Verified Fix

Tested on STM32F411CEU6 (Black Pill) @ 25 MHz HSE with I²S microphone (SPH0465):

✅ HAL_I2S_Init() succeeds

✅ DMA reception functional

✅ Manual and HAL-reported I²SCLK = 96 MHz

🗓️ Environment

STM32CubeMX v6.11.1

STM32CubeF4 v1.28.3 (Nov 2023)

Keil MDK 5.39 / GCC 13.2

STM32F411CEU6 (Device ID = 0x433 → F401xD/E signature)

📸 Optional Attachments

Include screenshots showing:

CubeMX Clock Tree (HSE = 25 MHz, PLLM = 25, PLLI2SN = 192, PLLI2SR = 2)

Fault/ErrorCode 0x10 from HAL_I2S_Init() before fix

Successful 96 MHz I²SCLK after patch

Suggested Labels: bug, HAL, STM32F411, RCC, I2S, CubeF4

Keywords for classification: HAL_RCCEx_GetPeriphCLKFreq, RCC, I2S, STM32F411, bug

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinghalHAL-LL driver-related issue or pull-request.invalidThis doesn't seem rightrccReset and Clock Controller

Type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions