Skip to main content
gil_dobjanschi
Associate III
August 13, 2026
Question

I3C target transmit does not trigger a callback upon completion

  • August 13, 2026
  • 1 reply
  • 42 views

Hi,

 

I am developing an I3C target application that responds to I3C private messages from the controller. The application starts by registering the Tx callback.

static void I3C_TxCompleteCallback(hal_i3c_handle_t *hi3c);

// The callback is registered during initialization
hal_status_t status = HAL_I3C_TGT_RegisterTxCpltCallback(hI3C, I3C_TxCompleteCallback);
if (status != HAL_OK) {
SWD_printf("HAL_I3C_TGT_RegisterTxCpltCallback failed.\n");
return status;
}

The target responds to the controller:

      hal_status_t status;
hal_i3c_handle_t *hI3C = mx_i3c1_gethandle();
status = HAL_I3C_TGT_Transmit_IT(hI3C, I3C_TxBuffer, 8);
if (status != HAL_OK) {
SWD_printf("HAL_I3C_TGT_Transmit_IT: %lx\n", status);
return status;
}

The controller receives 8 bytes of data and the data is correct but the TxComplete callback does not trigger on the target side.

I placed a breakpoint inside the HAL I3C_Tgt_ISR show below.

/**
* @brief Interrupt Sub-Routine which handles target transmit data in Interrupt mode.
* @param hi3c Pointer to a @ref hal_i3c_handle_t
* @param it_masks Flag Interrupt Masks flags to handle
* @retval HAL_OK Operation completed successfully
*/
static hal_status_t I3C_Tgt_Tx_ISR(hal_i3c_handle_t *hi3c, uint32_t it_masks)
{
I3C_TypeDef *p_i3cx;

p_i3cx = I3C_GET_INSTANCE(hi3c);

/* I3C Tx FIFO not full interrupt Check */
if (I3C_CHECK_FLAG(it_masks, LL_I3C_MISR_TXFNFMIS) != 0U)
{
if (hi3c->tx_count_byte > 0U)
{
hi3c->p_tx_func(hi3c);
}
}

/* I3C target frame complete event Check */
if (I3C_CHECK_FLAG(it_masks, LL_I3C_MISR_FCMIS) != 0U)
{
LL_I3C_ClearFlag_FC(p_i3cx);

/* Check if all data bytes are transmitted */
if (LL_I3C_GetXferDataCount(p_i3cx) == hi3c->data_size_byte)
{
LL_I3C_DisableIT(p_i3cx, LL_I3C_TGT_TX_IT);
I3C_StateIdle(hi3c);
#if (USE_HAL_I3C_REGISTER_CALLBACKS) && (USE_HAL_I3C_REGISTER_CALLBACKS == 1)
hi3c->p_tgt_tx_cplt_cb(hi3c);
#else
HAL_I3C_TGT_TxCpltCallback(hi3c);
#endif /* USE_HAL_I3C_REGISTER_CALLBACKS */
}
else
{
I3C_ErrorTreatment(hi3c);
}
}

/* I3C target wakeup event management ----------------------------------*/
if (I3C_CHECK_FLAG(it_masks, LL_I3C_MISR_WKPMIS) != 0U)
{
/* Clear WKP flag */
LL_I3C_ClearFlag_WKP(p_i3cx);

#if (USE_HAL_I3C_REGISTER_CALLBACKS) && (USE_HAL_I3C_REGISTER_CALLBACKS == 1)
hi3c->p_notify_cb(hi3c, HAL_I3C_TGT_NOTIFICATION_WKP);
#else
HAL_I3C_NotifyCallback(hi3c, HAL_I3C_TGT_NOTIFICATION_WKP);
#endif /* USE_HAL_I3C_REGISTER_CALLBACKS */
}

return HAL_OK;
}

When the interrupt occurs the hi3c->p_tx_func is called and sends the 8 bytes into the FIFO.  Once it completes the it_masks check that follows fails and therefore the Tx callback is not called:

  /* I3C target frame complete event Check */
if (I3C_CHECK_FLAG(it_masks, LL_I3C_MISR_FCMIS) != 0U)
{
// This code does not execute
}

Could you help me figure out why the Tx callback does not occur on the target side?

 

Thank you,

Gil

1 reply

gil_dobjanschi
Associate III
August 14, 2026

I looked into this a bit further. The LL_I3C_MISR_FCMIS flag reflects the Frame Complete Masked Interrupt Status. I checked that the controller receives the correct number of bytes, the received data is correct, and that there is a STOP at the end of the frame (SCA goes HIGH while SCL is HIGH). In fact the controller uses HAL_I3C_PRIVATE_WITH_ARB_STOP for the transaction so I would expect it generate the STOP at the end of the transaction.