cancel
Showing results for 
Search instead for 
Did you mean: 

Check I2C DMA position during onging write

WhoIsJohnGalt
Associate III

I am currently trying to figure out at what byte the slave sends a NACK during an I2C master write transfer.
When the slave sends the NACK after X bytes the error callback is called. Inside the error callback I am having trouble finding out at what byte the NACK occured (I want to know how many bytes were transferred fine and at what position the NACK was send).

if (HAL_I2C_Master_Seq_Transmit_DMA(i2c_handle, slave_addr, data, write_size, I2C_FIRST_AND_LAST_FRAME) != HAL_OK) {
 // error handling
}

void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef* /*hi2c*/) {
 // Never called
}

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef* hi2c) {
  uint32_t tx_cnt = __HAL_DMA_GET_COUNTER(hi2c->hdmatx);
}

I tried to register DMA callbacks, but they are cleared inside the HAL_I2C_Master_Seq_Transmit_DMA function and therefore never called... 

    if (HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel3, HAL_DMA_XFER_ABORT_CB_ID, DMAabortCallback) != HAL_OK) {
      Error_Handler();
    }
    if (HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel2, HAL_DMA_XFER_ABORT_CB_ID, DMAabortCallback) != HAL_OK) {
      Error_Handler();
    }

    if (HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel3, HAL_DMA_XFER_ERROR_CB_ID, DMAerrorCallback) != HAL_OK) {
      Error_Handler();
    }
    if (HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel2, HAL_DMA_XFER_ERROR_CB_ID, DMAerrorCallback) != HAL_OK) {
      Error_Handler();
    }


void DMAabortCallback(DMA_HandleTypeDef* const hdma) {
  uint32_t tx_cnt = __HAL_DMA_GET_COUNTER(hdma);
}

void DMAerrorCallback(DMA_HandleTypeDef* const hdma) {
  uint32_t tx_cnt = __HAL_DMA_GET_COUNTER(hdma);
}

I am using an STM32H534 MCU.

I am thankful for any help

Regards
John

3 REPLIES 3
TDK
Guru

__HAL_DMA_GET_COUNTER will return the value of the NDTR register.

The NDTR register starts out at the length you're sending and it ends at 0 when the transfer is complete. So if you send 10 bytes, and it's 7 in the error callback after a NACK, the NACK happened after 3 bytes were sent. Might be off by 1 if it preloads but I don't believe it does.

If you feel a post has answered your question, please click "Accept as Solution".

You may want to read the explanation to GPDMA_CxSR.FIFOL in the GPDMA chapter of RM0481.

JW

Thank you. The DMA channels have FIFO buffers (8 bytes in my case). And and the GPDMA_CxSR.FIFOL[7:0] bits contain the remaining write beats of the FIFO.

WhoIsJohnGalt_0-1736091773323.png

 

The problem I have now is that the HAL lib resets the fifo before calling the abort callback ...

WhoIsJohnGalt_1-1736092366654.png

I will try moving the call of the callback up to line 1000.