Skip to main content
Explorer II
March 5, 2025
Solved

AN5879 (I3C) for NUCLEO-H563ZI and XNUCLEO-IKS4A1

  • March 5, 2025
  • 1 reply
  • 453 views

Hello ST Team,

I'm trying to bring up I3C using a NUCLEO-H563ZI with XNUCLEO-IKS4A1 to boards stress I3C, and I'm using AN5879, which was thought for NUCLEO-H503RB and X-NUCLEO-IKS01A3 boards.

Regardless of the above, I still believe we should be able to work with these boards as they are I3C compatible, and the XNUCLEO-IKS4A1 is marked as the new alternative for the X-NUCLEO-IKS01A3 board.

I'm following AN5879 to introduce myself to I3C (and the entire STM32CubeIDE ecosystem), and I have found issues adding the extra code stated on page 31 (software settings for dynamic addressing).

Where precisely should these lines be introduced? For the four code blocks, I can identify the second and the fourth ones belonging to the main.c file. What about the first and third blocks? For the first, it seems I should create a new header file stm32_i3c_desc_target1.h, but even when creating this file and adding a reference in main.h the compiler struggles to find "TargetDesc_Typedef". My best guess is to include the third block at the last part of the MX_I3C1_Init function described in main.c.

Returning to the fourth block:

 

void HAL_I3C_TgtReqDynamicAddrCallback(I3C_HandleTypeDef *hi3c, uint64_t targetPayload)
{
	TargetDesc1.TARGET_BCR_DCR_PID = targetPayload;
	HAL_I3C_Ctrl_SetDynAddr(hi3c, TargetDesc1.DYNAMIC_ADDR);
}
void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}

 

Could you please give me a hand checking if this GPIO reference to pin 5 and GPIOA is still valid for the NUCLEO-H563ZI board?

Thank you, D.

    This topic has been closed for replies.
    Best answer by DanLumi

    I found out some answers after opening an example demo using I3C (I3C_Controller_Direct_Command_DMA).

    The first block:

    #define TARGET1_DYN_ADDR 0x32
    
    /********************/
    /* Target Descriptor */
    /********************/
    TargetDesc_TypeDef TargetDesc1 =
    {
     "TARGET_ID1",
     DEVICE_ID1,
     0x0000000000000000,
     0x00,
     TARGET1_DYN_ADDR,
    };

    should go in a new header file (named here desc_target1.h as in the example) and referenced in the main.c after including main.h:

    #include "main.h"
    #include "desc_target1.h"

    The typedef description should be added in main.h:

    /* USER CODE BEGIN ET */
    /* Target descriptor */
    typedef struct {
     char * TARGET_NAME; /*!< Marketing Target reference */
     uint32_t TARGET_ID; /*!< Target Identifier on the Bus */
     uint64_t TARGET_BCR_DCR_PID; /*!< Concatenation value of PID, BCR and DCR of the target */
     uint8_t STATIC_ADDR; /*!< Static Address of the target, value found in the datasheet of the device */
     uint8_t DYNAMIC_ADDR; /*!< Dynamic Address of the target preset by software/application */
    } TargetDesc_TypeDef;
    /* USER CODE END ET */

    The device ID also needs to be defined in the main.h file:

    /* USER CODE BEGIN Private defines */
    
    /* Define Target Identifier */
    #define DEVICE_ID1 0U
    
    /* USER CODE END Private defines */

    The third block can go after I3C is initialized (MX_I3C1_Init() in main.c):

    /* USER CODE BEGIN 2 */
    
     /* Assign dynamic address processus */
     if (HAL_I3C_Ctrl_DynAddrAssign_IT(&hi3c1, I3C_ONLY_ENTDAA) != HAL_OK)
     {
    	 /* Error_Handler() function is called when error occurs. */
    	 Error_Handler();
     }
    
    /* USER CODE END 2 */

    Regarding the last doubt from the fourth block,

    /* USER CODE BEGIN 4 */
    void HAL_I3C_TgtReqDynamicAddrCallback(I3C_HandleTypeDef *hi3c, uint64_t targetPayload)
    {
    	TargetDesc1.TARGET_BCR_DCR_PID = targetPayload;
    	HAL_I3C_Ctrl_SetDynAddr(hi3c, TargetDesc1.DYNAMIC_ADDR);
    }
    void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c)
    {
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    }
    /* USER CODE END 4 */

    I can now tell (please correct if I'm wrong) HAL_I3C_CtrlDAACpltCallback is called as an acknowledgement of a successful dynamic address assignment. So the way to tell the user of this can be, for example, a LED turn on:

    void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c)
    {
    	BSP_LED_On(LED_GREEN);
    }

     After these additions, I can compile, program the board and see SCL/SDA transactions.

    1 reply

    DanLumiAuthorAnswer
    Explorer II
    March 5, 2025

    I found out some answers after opening an example demo using I3C (I3C_Controller_Direct_Command_DMA).

    The first block:

    #define TARGET1_DYN_ADDR 0x32
    
    /********************/
    /* Target Descriptor */
    /********************/
    TargetDesc_TypeDef TargetDesc1 =
    {
     "TARGET_ID1",
     DEVICE_ID1,
     0x0000000000000000,
     0x00,
     TARGET1_DYN_ADDR,
    };

    should go in a new header file (named here desc_target1.h as in the example) and referenced in the main.c after including main.h:

    #include "main.h"
    #include "desc_target1.h"

    The typedef description should be added in main.h:

    /* USER CODE BEGIN ET */
    /* Target descriptor */
    typedef struct {
     char * TARGET_NAME; /*!< Marketing Target reference */
     uint32_t TARGET_ID; /*!< Target Identifier on the Bus */
     uint64_t TARGET_BCR_DCR_PID; /*!< Concatenation value of PID, BCR and DCR of the target */
     uint8_t STATIC_ADDR; /*!< Static Address of the target, value found in the datasheet of the device */
     uint8_t DYNAMIC_ADDR; /*!< Dynamic Address of the target preset by software/application */
    } TargetDesc_TypeDef;
    /* USER CODE END ET */

    The device ID also needs to be defined in the main.h file:

    /* USER CODE BEGIN Private defines */
    
    /* Define Target Identifier */
    #define DEVICE_ID1 0U
    
    /* USER CODE END Private defines */

    The third block can go after I3C is initialized (MX_I3C1_Init() in main.c):

    /* USER CODE BEGIN 2 */
    
     /* Assign dynamic address processus */
     if (HAL_I3C_Ctrl_DynAddrAssign_IT(&hi3c1, I3C_ONLY_ENTDAA) != HAL_OK)
     {
    	 /* Error_Handler() function is called when error occurs. */
    	 Error_Handler();
     }
    
    /* USER CODE END 2 */

    Regarding the last doubt from the fourth block,

    /* USER CODE BEGIN 4 */
    void HAL_I3C_TgtReqDynamicAddrCallback(I3C_HandleTypeDef *hi3c, uint64_t targetPayload)
    {
    	TargetDesc1.TARGET_BCR_DCR_PID = targetPayload;
    	HAL_I3C_Ctrl_SetDynAddr(hi3c, TargetDesc1.DYNAMIC_ADDR);
    }
    void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c)
    {
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    }
    /* USER CODE END 4 */

    I can now tell (please correct if I'm wrong) HAL_I3C_CtrlDAACpltCallback is called as an acknowledgement of a successful dynamic address assignment. So the way to tell the user of this can be, for example, a LED turn on:

    void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c)
    {
    	BSP_LED_On(LED_GREEN);
    }

     After these additions, I can compile, program the board and see SCL/SDA transactions.