Skip to main content
Associate II
May 21, 2026
Question

STM32H743VGT6 how to use slave I2C+DMA

  • May 21, 2026
  • 1 reply
  • 86 views

STM32H743VGT6 how to use slave I2C+DMA
Currently, this usage is fine. However, when using the DMA function, it will trigger an ER interrupt.
HAL_I2C_Slave_Seq_Receive_DMA, How to use it? Are there any examples?

// 从机地址匹配回调函数
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
 if (hi2c->Instance == I2C1)
 {
 if (TransferDirection == I2C_DIRECTION_TRANSMIT)
 {
 Rx_len = 0;
 memset(I2C_rxBuffer,0,4);
 HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, I2C_rxBuffer, 1, I2C_FIRST_AND_LAST_FRAME);
 }
 else
 {
 HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1, I2C_txBuffer, Tx_len, I2C_FIRST_AND_LAST_FRAME);
 }
 }
}

 

1 reply

mbarg.1
Senior III
May 21, 2026

I do use I2c+DMA with AZrtos - up to you to port to your OS

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1 __attribute__((weak));
I2C_HandleTypeDef hi2c2 __attribute__((weak));
I2C_HandleTypeDef hi2c3 __attribute__((weak));
I2C_HandleTypeDef hi2c4 __attribute__((weak));

/* Private function prototypes -----------------------------------------------*/

/* Global variables ----------------------------------------------------------*/

I2cServer_t hI2cServer;
#if 0
#ifdef I2C_USE_1
ALIGN_32BYTES (uint8_t hi2cbuffRx[32]) __attribute__((section(".DmaArraySection")));
ALIGN_32BYTES (uint8_t hi2cbuffTx[32]) __attribute__((section(".DmaArraySection")));
#endif
#endif

#ifdef I2C_USE_2
ALIGN_32BYTES (uint8_t hi2cbuffRx[I2C_TX_BUFFER_SIZE]) __attribute__((section(".DmaArraySection")));
ALIGN_32BYTES (uint8_t hi2cbuffTx[I2C_TX_BUFFER_SIZE]) __attribute__((section(".DmaArraySection")));
#endif
#ifdef I2C_USE_3
ALIGN_32BYTES (uint8_t hi2cbuffRx[32]) __attribute__((section(".DmaArraySection")));
ALIGN_32BYTES (uint8_t hi2cbuffTx[32]) __attribute__((section(".DmaArraySection")));
#endif
#ifdef I2C_USE_4
ALIGN_32BYTES (uint8_t hi2cbuffRx[32]) __attribute__((section(".DmaArraySection")));
ALIGN_32BYTES (uint8_t hi2cbuffTx[32]) __attribute__((section(".DmaArraySection")));
#endif

/* Private user code ---------------------------------------------------------*/

/* HAL functions redefined ---------------------------------------------------*/

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* HAL_I2C_MasterTxCpltCallback						 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions set event according to interrupt					 */
/*		and wakes up calling thread.									 */
/* */
/* INPUT */
/* */
/*		hi2c					-	ptr to i2c andle					 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* i2c hardware			 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {

#ifdef I2C_USE_1
	if (hi2c == &hi2c1) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt1, TX_OR);
	}
#endif
#ifdef I2C_USE_2
	if (hi2c == &hi2c2) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt2, TX_OR);
	}
#endif
#ifdef I2C_USE_3
	if (hi2c == &hi2c3) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt3, TX_OR);
	}
#endif
//#ifdef I2C_USE_4
	if (hi2c == &hi2c4) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt4, TX_OR);
	}
//#endif
	return;
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* HAL_I2C_MasterRxCpltCallback						 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions set event according to interrupt					 */
/*		and wakes up calling thread.									 */
/* */
/* INPUT */
/* */
/*		hi2c					-	ptr to i2c andle					 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* i2c hardware			 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {

#ifdef I2C_USE_1
	if (hi2c == &hi2c1) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt1, TX_OR);
	}
#endif
#ifdef I2C_USE_2
	if (hi2c == &hi2c2) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt2, TX_OR);
	}
#endif
#ifdef I2C_USE_3
	if (hi2c == &hi2c3) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt3, TX_OR);
	}
#endif
//#ifdef I2C_USE_4
	if (hi2c == &hi2c4) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_TxRxCplt4, TX_OR);
	}
//#endif
	return;
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* HAL_I2C_MemRxCpltCallback							 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions set event according to interrupt					 */
/*		and wakes up calling thread.									 */
/* */
/* INPUT */
/* */
/*		hi2c					-	ptr to i2c andle					 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* i2c hardware			 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {

#ifdef I2C_USE_1
	if (hi2c == &hi2c1) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_MemTxRxCplt1, TX_OR);
	}
#endif
#ifdef I2C_USE_2
	if (hi2c == &hi2c2) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_MemTxRxCplt2, TX_OR);
	}
#endif
#ifdef I2C_USE_3
	if (hi2c == &hi2c3) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_MemTxRxCplt3, TX_OR);
	}
#endif
//#ifdef I2C_USE_4
	if (hi2c == &hi2c4) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_MemTxRxCplt4, TX_OR);
	}
//#endif
	return;
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* HAL_I2C_ErrorCallback								 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions set event according to interrupt					 */
/*		and wakes up calling thread.									 */
/* */
/* INPUT */
/* */
/*		hi2c					-	ptr to i2c andle					 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* i2c hardware			 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {

#ifdef I2C_USE_1
	if (hi2c == &hi2c1) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_Err1, TX_OR);
	}
#endif
#ifdef I2C_USE_2
	if (hi2c == &hi2c2) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_Err2, TX_OR);
	}
#endif
#ifdef I2C_USE_3
	if (hi2c == &hi2c3) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_Err3, TX_OR);
	}
#endif
//#ifdef I2C_USE_4
	if (hi2c == &hi2c4) {
		tx_event_flags_set(&hI2cServer.i2c_event_group, I2C_EVENT_Err4, TX_OR);
	}
//#endif
	return;
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* mb_I2C_write										 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions write data to I2C with DMA							 */
/*		and waits for completion.										 */
/* */
/* INPUT */
/* */
/*		mb_i2c_cmd_t h			ptr to handle with input and output val */
/* */
/* OUTPUT */
/* */
/* GLOBALS 								 */
/* */
/*		 hi2cbuffTx			Ptr to tx buffer */
/*		 */
/* CALLS */
/* */
/* 	 	HAL_I2C_Master_Transmit_DMA										 */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* I2C Device driver		 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void mb_I2C_write(mb_i2c_cmd_t *h) {

	/*	clean cache		*/
	SCB_CleanDCache_by_Addr((uint32_t*) hi2cbuffTx, I2C_TX_BUFFER_SIZE);
	/*	start transmit data with DMA		*/
	h->event = HAL_I2C_Master_Transmit_DMA(h->hi2c, h->slave, hi2cbuffTx, h->size);
	if (h->event != HAL_OK) {
		/*	we have a HAL error -busy or other - stop DMA		*/
		HAL_DMA_Abort(h->hi2c->hdmatx);
		return;
	}
	/*	wait for event or timeout		*/
	if( tx_event_flags_get(&hI2cServer.i2c_event_group, I2C_ANY_EVENT, TX_OR_CLEAR, (ULONG *)&h->event, h->eventWait) == TX_SUCCESS) {
			/*	we got an event that operation was completed		*/
	} else {
		/*	we got a timeout - no device present? - stop DMA		*/
		HAL_DMA_Abort(h->hi2c->hdmatx);
		/*	set event		*/
		h->event = I2C_EVENT_Timeout;
	}
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* mb_I2C_read										 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions read data from I2C with DMA						 */
/*		and waits for completion.										 */
/* */
/* INPUT */
/* */
/*		mb_i2c_cmd_t h		ptr to handle with input and output val 	 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* I2C Device driver		 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void mb_I2C_read(mb_i2c_cmd_t *h) {
	/*	start receive data with DMA		*/
	h->event = HAL_I2C_Master_Receive_DMA(h->hi2c, h->slave, hi2cbuffRx, h->size);
	if (h->event != HAL_OK) {
		/*	we have a HAL error -busy or other		*/
		/*	stop DMA		*/
		HAL_DMA_Abort(h->hi2c->hdmarx);
		return;
	}
	/*	wait for event or timeout		*/
	if(tx_event_flags_get(&hI2cServer.i2c_event_group, I2C_ANY_EVENT, TX_OR_CLEAR, (ULONG *)&h->event, h->eventWait) == TX_SUCCESS) {
	} else {
		/*	we got a timeout - no device present?		*/
		/*	set returned status		*/
		h->event = I2C_EVENT_Timeout;
	}
}

/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* mb_I2C_mem_read										 PORTABLE C */
/* */
/* AUTHOR */
/* */
/* Mike Bargauan														 */
/* */
/* DESCRIPTION */
/* */
/* This functions read data from I2C memory with DMA					 */
/*		and waits for completion.										 */
/* */
/* INPUT */
/* */
/*		mb_i2c_cmd_t h		ptr to handle with input and output val		 */
/* */
/* OUTPUT */
/* */
/* CALLS */
/* 	 	tx_event_flags_set												 */
/* */
/* CALLED BY */
/* */
/* I2C Device driver		 				 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/**************************************************************************/
void mb_I2C_mem_read(mb_i2c_cmd_t *h) {

	h->event = HAL_I2C_Mem_Read_DMA(h->hi2c, h->slave, h->address, I2C_MEMADD_SIZE_8BIT, hi2cbuffRx, h->size);
	if (h->event != HAL_OK) {
		/*	we have a HAL error -busy or other		*/
		/*	stop DMA		*/
		HAL_DMA_Abort(h->hi2c->hdmatx);
		HAL_DMA_Abort(h->hi2c->hdmarx);
		return;
	}
	/*	wait for event or timeout		*/
	if(tx_event_flags_get(&hI2cServer.i2c_event_group, I2C_ANY_EVENT, TX_OR_CLEAR, (ULONG*) &h->event, h->eventWait) == TX_SUCCESS) {
		SCB_InvalidateDCache_by_Addr((uint32_t*) hi2cbuffRx, I2C_RX_BUFFER_SIZE);
	} else {
		/*	we got a timeout - no device present?		*/
		/*	stop DMA		*/
		HAL_DMA_Abort(h->hi2c->hdmatx);
		HAL_DMA_Abort(h->hi2c->hdmarx);
		/*	set returned status		*/
		h->event = I2C_EVENT_Timeout;
	}
}
AngusHZAuthor
Associate II
May 21, 2026

Have the slave i2c+DMA?
Master and slave is different