Skip to main content
Graduate
January 3, 2025
Solved

Check I2C DMA position during onging write

  • January 3, 2025
  • 3 replies
  • 715 views

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

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

    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.

    3 replies

    Super User
    January 4, 2025

    __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.

    Super User
    January 5, 2025

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

    JW

    WhoIsJohnGaltAuthorAnswer
    Graduate
    January 5, 2025

    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.

    Super User
    January 5, 2025

    Generally, using Cube/HAL gets counterproductive as soon as you want to do anything which cannot be directly clicked in CubeMX. 

     

    JW