2026-05-21 2:08 AM
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);
}
}
}
2026-05-21 2:26 AM
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;
}
}
2026-05-21 2:36 AM
Have the slave i2c+DMA?
Master and slave is different