cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H563 I3C SDA line driven low by a target cause unexpected behavior

SUPA786
Associate

After STM32H5 I3C initialized as a controller, without any IBI, HotJoin Enabled, pull low SDA line will case SCL unstopped-toggle, as figure  

 STM32h5_I3C Errata.png

I had searched STM32H563 Errata 2.5.13, and got something likes this behavior :

I3C controller: unexpected first frame with a 0x7F address when the I3C peripheral is enabled
Description
After I3C has been initialized as controller, an unexpected frame is generated when the I3C peripheral is enabled.
The issue occurs after the following sequence:
1. I3C is initialized as I3C controller (CRINIT bit is set in I3C_CFGR whereas EN bit is kept cleared in
I3C_CFGR).
2. I3C is enabled (EN bit set in I3C_CFGR).
As a result, the I3C controller can incorrectly detect that the SDA line has been driven low by a target, interpret it
as a start request, activate the SCL clock, and generate a 0x7F address followed by RNW bit = 1 that is not
acknowledged.
This first frame completes without any other impact than this unexpected I3C bus activity.

Workaround
Respect the sequence below during I3C controller initialization:
1. Instead of configuring the alternate GPIO of the SDA line without any pull-up, temporary enable the GPIO pullup.
2. After a delay of 1 ms, disable GPIO pull-up.
3. Initialize I3C as I3C controller by setting CRINIT in I3C_CFGR whereas EN bit is kept cleared in I3C_CFGR.
4. Enable I3C by setting EN bit in I3C_CFGR.
As a result the I3C controller does not detect SDA low when it is enabled, and no unexpected frame is generated

 

**Question**

I had followed the errata solution, but the problem is still not solved, 

Do you have any idea?

Here is my code :

I3C1->CFGR &= ~(I3C_CFGR_EN | I3C_CFGR_CRINIT);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);
HAL_Delay(1);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_9, LL_GPIO_PULL_NO);
I3C1->CFGR |= I3C_CFGR_CRINIT;

I3C1->CFGR |= I3C_CFGR_EN ;

 

3 REPLIES 3
Foued_KH
ST Employee

Hello @SUPA786 , 

First of all, could you please specify your HW setup?
Then, the I3C controller parameters .

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello, @Foued_KH , thanks for your reply, 

I am using demo board [NUCLEOH-563ZI] for my Hardware without connect any slave device, 

I keep pin PB8(I3C1_SCL), PB9(I3C1_SDA) floating when power up, and then pull SDA to GND cause SCL unstopped-toggle, as figure above

In Legacy I2C Bus scenario, there is other Host I2C share the bus, it might be a problem.

Here is my I3C initial code :

int i3c_masterinit(void)
{
    /* USER CODE BEGIN I3C1_Init 0 */
    /* USER CODE END I3C1_Init 0 */
    I3C_FifoConfTypeDef sFifoConfig = {0};
    I3C_CtrlConfTypeDef sCtrlConfig = {0};
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

    /* USER CODE BEGIN I3C1_MspInit 0 */

    /* USER CODE END I3C1_MspInit 0 */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I3C1;
    PeriphClkInitStruct.I3c1ClockSelection = RCC_I3C1CLKSOURCE_PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_I3C1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I3C1 GPIO Configuration
    PB8     ------> I3C1_SCL
    PB9     ------> I3C1_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    //GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF3_I3C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    /* USER CODE BEGIN I3C1_Init 1 */    
   
   
    U32  I3C_PushPull_Baudrate  = 1000000;
    U32  I3C_OpenDrain_Baudrate =  500000;
    U32  I2C_Baudrate           =  100000;
    U32  I3C_HighDuration_ns    =      40;
   
    U32  tI3CCLK_ns = I3C_CORE_PERIOD_NS;
    U32  halfCLK_ns = I3C_CORE_PERIOD_NS/2;
   
    U32  I3C_PP_Period_ns = 1e9 / I3C_PushPull_Baudrate;        // baud:12.5MKz -> period:80ns
    U32  I3C_OD_Period_ns = 1e9 / I3C_OpenDrain_Baudrate;
    U32  I2C_Period_ns    = 1e9 / I2C_Baudrate;
   
    U32  PP_LowDuration_ns   = I3C_PP_Period_ns - I3C_HighDuration_ns;
    U32  OD_LowDuration_ns   = I3C_OD_Period_ns - I3C_HighDuration_ns;    
    U32  I2C_HighDuration_ns = I2C_Period_ns    - OD_LowDuration_ns;  

    /* USER CODE END I3C1_Init 1 */
    hi3c1.Instance = I3C1;
    hi3c1.Mode = HAL_I3C_MODE_CONTROLLER;
    hi3c1.Init.CtrlBusCharacteristic.SDAHoldTime = HAL_I3C_SDA_HOLD_TIME_1_5;
    hi3c1.Init.CtrlBusCharacteristic.WaitTime = HAL_I3C_OWN_ACTIVITY_STATE_0;
    //hi3c1.Init.CtrlBusCharacteristic.SCLI3CHighDuration = 0x09; //40ns
    //hi3c1.Init.CtrlBusCharacteristic.SCLPPLowDuration = 0x09;
    //hi3c1.Init.CtrlBusCharacteristic.SCLODLowDuration = 0x7c;
    //hi3c1.Init.CtrlBusCharacteristic.SCLI2CHighDuration = 0x7c; //500ns > Ti3c = 4ns > Fi3c = 250MHz
    hi3c1.Init.CtrlBusCharacteristic.SCLI3CHighDuration = (I3C_HighDuration_ns + halfCLK_ns)/tI3CCLK_ns - 1;
    hi3c1.Init.CtrlBusCharacteristic.SCLPPLowDuration   = (PP_LowDuration_ns   + halfCLK_ns)/tI3CCLK_ns - 1;
    hi3c1.Init.CtrlBusCharacteristic.SCLODLowDuration   = (OD_LowDuration_ns   + halfCLK_ns)/tI3CCLK_ns - 1;
    hi3c1.Init.CtrlBusCharacteristic.SCLI2CHighDuration = (I2C_HighDuration_ns + halfCLK_ns)/tI3CCLK_ns - 1;
    hi3c1.Init.CtrlBusCharacteristic.BusFreeDuration = 0x6a;
    hi3c1.Init.CtrlBusCharacteristic.BusIdleDuration = 0xf8;
    if (HAL_I3C_Init(&hi3c1) != HAL_OK)
    {
        Error_Handler();
    }

    /** Configure FIFO
    */
    sFifoConfig.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4;
    sFifoConfig.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4;
    sFifoConfig.ControlFifo = HAL_I3C_CONTROLFIFO_ENABLE;//HAL_I3C_CONTROLFIFO_DISABLE
    sFifoConfig.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE;
    if (HAL_I3C_SetConfigFifo(&hi3c1, &sFifoConfig) != HAL_OK)
    {
        Error_Handler();
    }

    /** Configure controller
    */
    sCtrlConfig.DynamicAddr = 0;
    sCtrlConfig.StallTime = 0x00;
    sCtrlConfig.HotJoinAllowed = DISABLE;
    sCtrlConfig.ACKStallState = DISABLE;
    sCtrlConfig.CCCStallState = DISABLE;
    sCtrlConfig.TxStallState = DISABLE;
    sCtrlConfig.RxStallState = DISABLE;
    sCtrlConfig.HighKeeperSDA = DISABLE;
    if (HAL_I3C_Ctrl_Config(&hi3c1, &sCtrlConfig) != HAL_OK)
    {
        Error_Handler();
    }
  /* USER CODE BEGIN I3C1_Init 2 */
    I3C1->CFGR &= ~(I3C_CFGR_EN | I3C_CFGR_CRINIT);
   
    LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);
    HAL_Delay(10);
    LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_9, LL_GPIO_PULL_NO);    
   

    HAL_Delay(10);
    I3C1->CFGR |= (I3C_CFGR_EN | I3C_CFGR_CRINIT);
   

  /* USER CODE END I3C1_Init 2 */
    return 0;
}

 

 

 

 

Foued_KH
ST Employee

Hello @SUPA786 ,

If you disable the IBI and HotJoin as well, you will not see this behavior.
My recommendation is to connect an I3C target on the bus : 
When using a sensor as an I3C target, you need to check the maximum frequency for the communication.
If you are using another STM32H5 MCU as an I3C target, you can communicate at 12.5 MHz.

Let me know if this helps you!

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.