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

ST Technical Moderator
June 22, 2026

Hello ​@gil_dobjanschi 

It seems the issue is related to the generated code from MX. An internal ticket CDM0063708 is submitted to dedicated team for further investigation.

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
gil_dobjanschi
Senior
August 5, 2026

Hi ​@FBL,

 

Could you kindly provide an update for this issue? I tested ny application with MX2 version 1.1.1 generated code and I am getting the same behavior.

 

Thank you,

Gil

ST Technical Moderator
August 6, 2026

Hi ​@gil_dobjanschi 

Sorry for my late reply. Our teams were not able to reproduce the issue on our side. Could you please confirm whether, during debugging, you start the target application before launching the controller?

This step is important to ensure that the target is fully initialized and ready to respond to the controller’s private I3C communication requests.

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
gil_dobjanschi
Senior
August 6, 2026

Hi ​@FBL,

I did more debugging to try to understand the nature of the problem. I have a few comments/observations:

  1. The target is started before launching the controller. I don’t see any errors on the target side.
  2. The clock that is started on I3C_SCL during initialization is 2.5MHz.
  3. I noticed that after reset I3C_SDA goes LOW for 150ms (or more) and during this time the I3C_SCL stops. Once I3C_SDA goes HIGH again the I3C_SCL resumes.
  4. The error that occurs on the controller side as soon as I start the Dynamic Address Allocation is 0x11.

In stm32c5xx_hal_i3c.h this error code is defined as follows:

#define HAL_I3C_CTRL_ERROR_1          (LL_I3C_CONTROLLER_ERROR_CE1 | I3C_SER_PERR) 
/*!< 0x11 Controller detected that transmitted data on the bus is different from expected */

I attached the controller and target ioc2 files for reference.

Thank you,

Gil

gil_dobjanschi
Senior
August 10, 2026

Hi @ethonbrooks0707,

Unfortunately, comparing driver 2.1.0 with 2.0.0 hasn't been possible on my end, as MX2 does not allow switching to an older package — even when it recognizes the package as locally installed. To make matters worse, even if switching were possible, all generated files changed during the migration from 2.0.0 to 2.1.0, which makes pinpointing the root cause of the issue  challenging.

I decided to start the project from scratch, hoping a clean build would reveal something obvious. The result was the same — as soon as the I3C_SCL GPIO is configured during I3C initialization, a 2.5MHz clock signal appears on that pin. This happens even when no I3C target is connected to the controller, and clearly before Dynamic Address Allocation (DAA) is initiated. It is worth noting that according to the I3C specification, both lines should remain HIGH after reset.

I also tried changing the MX2 I3C Bus Usage setting from "I3C pure bus" to "I3C and I2C mixed bus". Interestingly, the I3C_SCL line initializes correctly to HIGH in this configuration. However, DAA still does not work in this case, though that appears to be a separate issue altogether.

I'm still don’t understand why this behavior does not appear on your end. Afterall the behavior that I am seeing is due just to the initialization.

 

Best regards, 

Gil

 

gil_dobjanschi
Senior
August 11, 2026

Hi ​@FBL & ​@ethonbrooks0707,

 

I continued the investigation by using the ‘I3C and I2C mixed bus’ setting instead of using ‘I3C pure bus’ because, with this setting, the state of I3C_SCL after initializing I3C using the MX2 code is correct (HIGH).

I tested my code in two scenarios:

  1. By powering the controller and the target off and then back on and
  2. Keeping the power on and resetting the controller and then the target (in that order).

The DAA works fine in both these scenarios.

My conclusion is that ‘I3C and I2C mixed bus’ DAA works, while ‘I3C pure bus’ does not (I3C_SCL clock is running after initialization). Clearly this is not okay; I would like to understand why the ‘I3C pure bus’ scenario does not work and it used to work with 2.0.0 drivers.

 

Regards,

Gil

ST Technical Moderator
August 13, 2026

Hi ​@gil_dobjanschi 

First, under Pack Manager you can manage the global packs required for STM32CubeMX2, and select .pack from local path 

 

To help narrow down the root cause, could you capture or log the I3C register state just before SCL starts toggling, especially the key timing/control registers such as I3C_TIMINGR0 and I3C_TIMINGR2?
It would be useful to inspect the controller state machine or possibly timing configuration

Since the DAA failure reports 0x11 : CE1/PERR, it may also be worth checking whether the bus timing params, particularly tSU_ODtSU_PP, and tSCO, as these may require adjustment in the timing registers.

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
gil_dobjanschi
Senior
August 13, 2026

Hi ​@FBL ,

 

I captured the values of the following registers just before the GPIO for the I3C_SCL is enabled which is the time I start seeing the toggles on the oscilloscope. 

I3C_TIMINGR0 = 0x00330505;

I3C_TIMINGR1 = 0x001D008E;

I3C_TIMINGR2 = 0x00009303;

 

I don’t know where to find: tSU_ODtSU_PP, and tSCO.

 

Thank you for looking into this,

Gil

ST Technical Moderator
August 18, 2026

Hi ​@gil_dobjanschi 

These are timing margins used by the peripheral to meet the I3C spec.
If they were too short or misconfigured, the controller may generate edges too early or too late, which can lead to DAA fail. So, from the values you read back, the controller is configured with the pure I3C timing set without issues. 

 

The mixed bus values would instead be:

  • I3C_TIMINGR0 = 0x2A640505
  • I3C_TIMINGR1 = 0x4C008E

HAL_I3C_CTRL_SetConfig is never changed from HAL2.0 to HAL2.1. Did you check your kernel clock source ? Maybe something has changed in your HW setup ?

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
gil_dobjanschi
Senior
August 19, 2026

Hi ​@FBL,

The hardware has not changed and please note that I3C_SCL is toggling after initialization (and therefore before DAA). I tried many MX2 settings but the ones that work for me (I3C_SCL stays HIGH after initialization) are: Bus usage = I3C and I2C mixed bus, I3C frequency = 12500, I2C frequency = 400 and Duty cycle (%) = 50. These MX2 settings correspond to the following timing values:

  • I3C_TIMINGR0 = 0xACBA0505
  • I3C_TIMINGR1 = 0x77008E

I also checked the clock used by the controller and the target I3C peripheral and it is/was 144MHz. The HCLK is/was 144MHz as well.

 

Thank you for the help,

Gil

ST Technical Moderator
August 19, 2026

Hi ​@gil_dobjanschi 

For Pure bus test case, can you check this configuration? 

Timing Register 0: 0x00550505:

Just for your information, the frequency of Open drain is set in this case to 1.56 MHz

Bits 31:24 SCLH_I2C[7:0] = 0x00: No I2C devices connected on the bus

Bits 23:16 SCLL_OD[7:0] = 0x55: SCL low duration in open drain phases tSCLL_OD = 597ns

Bits 15:8 SCLH_I3C[7:0]: = 0x05: SCL high duration tSCLH_I3C=  41ns

Bits 7:0 SCLL_PP[7:0]: = 0x05: SCL low duration in I3C push-pull phases  tSCLL_PP = 41ns
 

Check or dump the I3C status error register and capture the waveform to check SDA and SCL behavior. 

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
gil_dobjanschi
Senior
August 19, 2026

Hi ​@FBL ,

In the mx_i3c1_init MX2 generated code I changed the value of the timing_reg0 to 0x00550505:

  /**
* I3C1 timing_reg0 calculated by CubeMX2 with:
* - SDA rise time = 350 ns
* - Input frequency = 144 MHz
* - Bus usage = UTILS_I3C_I2C_MIXED_BUS
* - I3C bus frequency = 12.5 MHz
* - I2C bus frequency = 400 KHz
* - I2C and I3C duty cycle = 50 %
* I3C1 timing_reg1 calculated by CubeMX2 with:
* - Wait time = LL_I3C_OWN_ACTIVITY_STATE_0
*/
hal_i3c_ctrl_config_t i3c_ctrl_config;
//i3c_ctrl_config.timing_reg0 = 0xACBA0505UL;
i3c_ctrl_config.timing_reg0 = 0x00550505UL;
i3c_ctrl_config.timing_reg1 = 0x77008EUL;
if (HAL_I3C_CTRL_SetConfig(&hI3C1, &i3c_ctrl_config) != HAL_OK)
{
return NULL;
}

The output of the scope right after the initialization shows pulses with a frequency of 1.573MHz.

The value of hI3C1->last_error_codes is 0 while mx_i3c1_init is executing.

Thank you,

Gil