Skip to main content
gil_dobjanschi
Senior
June 21, 2026
Solved

I3C Controller Initialization Problem

  • June 21, 2026
  • 15 replies
  • 353 views

Hello,

I have a project that uses I3C to connect a Nucleo-C562RE with an STM32C542CCT6 MCU. The setup was working fine with HAL 2.0.0 but it does not work in 2.1.0. I generated the code with MX2 and I observed that it is identical to the code in the private_it_controller example code. I stepped through the mx_i3c1_init function and I noticed that the moment the GPIO for SDA and SCL are enabled, the I3C clock (SCL) is turned on (visible on the oscilloscope) and does not stop. I don’t see how this could be correct. When I try to start DAA it fails instantly (the error callback is invoked) and the SDA line never changes state (it stays HIGH after reset).

Can someone help with this issue?

Thank you,

Gil

Best answer by gil_dobjanschi

Hi ​@FBL,

 

I got the code working. Here is how I modified the code generated by MX2.

In the HAL_I3C_CTRL_SetConfig function I commented out the LL_I3C_Enable invocation. Since in that same function LL_I3C_SetMode is invoked CRINIT bit is set and EN flag is not set because I commented out LL_I3C_Enable.

 

In mx_i3c1_init I added the following workaround code that pulls up the SDA line temporarily and then sets the EN bit. After that SDA goes back to the normal push-pull configuration. This sequence ensures that SDA is HIGH when EN is set.

  /**
[GPIO Pin] ------> [Signal Name] ------> [Labels]

PB5 ------> I3C1_SDA ------> PB5
**/
// ----------- BEGIN Workaround ----------------
// Temporarily enable SDA pull-up
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = LL_GPIO_OUTPUT_OPENDRAIN;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_HIGH;
gpio_config.alternate = HAL_GPIO_AF_3;
HAL_GPIO_Init(PB5_PORT, PB5_PIN, &gpio_config);

// Enable I3C
LL_I3C_Enable(I3C_GET_INSTANCE(&hI3C1));

// ----------- END Workaround ----------------

gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_NO;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_HIGH;
gpio_config.alternate = HAL_GPIO_AF_3;
HAL_GPIO_Init(PB5_PORT, PB5_PIN, &gpio_config);

The MX2 Bus usage is set to “I3C pure bus”, the I3C frequency is set to the maximum value of 12500 and the Duty cycle I3C is set to 50.

 

Reset the Controller, reset the Target (in my case another STM32) then initiate DAA. It works every time. If I power on the Controller and the Target together and then perform DAA everything works fine as well.

 

Regards,

Gil

15 replies

gil_dobjanschi
Senior
August 20, 2026

Hi ​@FBL,

I searched to see if others are having the trouble that I am having and I found this with STM32 Sidekick:

On STM32H563xx, an I3C controller can show constant SCL ticking because, during enable/initialization, it may wrongly detect SDA low as a start request, then generate an unexpected frame with address 0x7F and RNW = 1, which is not acknowledged. The documented workaround is to temporarily enable a GPIO pull-up on SDA, wait 1 ms, then disable the pull-up before completing the normal I3C controller initialization and enable sequence.

Detailed Explanation

Erratum behavior

After initialization as an I3C controller by setting CRINIT in I3C_CFGR with EN cleared, then later setting EN, the peripheral can incorrectly interpret a target-driven SDA low level as a start request. When this happens, the controller activates SCL and transmits an unexpected first frame containing 0x7F with RNW = 1, and that frame is not acknowledged. The stated impact is unexpected I3C bus activity, observed as constant SCL ticking.

Workaround

Use this initialization sequence to avoid the erroneous start detection:

  1. Temporarily enable the GPIO pull-up on SDA instead of configuring the alternate-function GPIO with no pull-up.
  2. Wait 1 ms.
  3. Disable the GPIO pull-up.
  4. Initialize I3C as controller by setting CRINIT in I3C_CFGR while keeping EN cleared.
  5. Enable I3C by setting EN in I3C_CFGR.

This sequence prevents the controller from seeing SDA low at enable time, which avoids the unexpected first frame and the resulting constant SCL activity.

Additional context

The STM32H563 I3C peripheral itself supports controller operation with SCL frequencies up to 12.5 MHz, and its clock timing is configured through I3C_TIMINGR0, while additional stall-time adjustment is available through I3C_TIMINGR2. In other words, this erratum is described as an unexpected initialization-side bus activity issue, not simply a normal timing-register configuration topic.

 

It sounds like the exact problem I am running into. I verified with the scope that when LL_I3C_Enable is called (EN flag is set) SDA is low by modifying the LL_I3C_Enable code like this:

__STATIC_INLINE void LL_I3C_Enable(I3C_TypeDef *p_i3c)
{
__asm__ volatile ("sev": : :"memory");
STM32_SET_BIT(p_i3c->CFGR, I3C_CFGR_EN);
}

The oscilloscope was monitoring SDA and an EVENTOUT pin that is pulsed when the above assembly instruction is executed. Sure enough SDA was LOW. If I setup SDA to be pulled up as the Workaround stipulates then set the EN bit, SCL will initialize correctly to HIGH (it does not pulse when initialization completes). It seems that I am on the right track.

 

Regards,

Gil

gil_dobjanschi
gil_dobjanschiAuthorBest answer
Senior
August 20, 2026

Hi ​@FBL,

 

I got the code working. Here is how I modified the code generated by MX2.

In the HAL_I3C_CTRL_SetConfig function I commented out the LL_I3C_Enable invocation. Since in that same function LL_I3C_SetMode is invoked CRINIT bit is set and EN flag is not set because I commented out LL_I3C_Enable.

 

In mx_i3c1_init I added the following workaround code that pulls up the SDA line temporarily and then sets the EN bit. After that SDA goes back to the normal push-pull configuration. This sequence ensures that SDA is HIGH when EN is set.

  /**
[GPIO Pin] ------> [Signal Name] ------> [Labels]

PB5 ------> I3C1_SDA ------> PB5
**/
// ----------- BEGIN Workaround ----------------
// Temporarily enable SDA pull-up
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = LL_GPIO_OUTPUT_OPENDRAIN;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_HIGH;
gpio_config.alternate = HAL_GPIO_AF_3;
HAL_GPIO_Init(PB5_PORT, PB5_PIN, &gpio_config);

// Enable I3C
LL_I3C_Enable(I3C_GET_INSTANCE(&hI3C1));

// ----------- END Workaround ----------------

gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_NO;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_HIGH;
gpio_config.alternate = HAL_GPIO_AF_3;
HAL_GPIO_Init(PB5_PORT, PB5_PIN, &gpio_config);

The MX2 Bus usage is set to “I3C pure bus”, the I3C frequency is set to the maximum value of 12500 and the Duty cycle I3C is set to 50.

 

Reset the Controller, reset the Target (in my case another STM32) then initiate DAA. It works every time. If I power on the Controller and the Target together and then perform DAA everything works fine as well.

 

Regards,

Gil

ST Technical Moderator
August 20, 2026

Thank you for your feedback ​@gil_dobjanschi 

I will escalate this errata on C5 to our dedicated team. Internal ticket number : CDM0065606 

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL