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

1 ACCEPTED SOLUTION

Accepted Solutions

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.

View solution in original post

4 REPLIES 4
TDK
Super User

__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".
waclawek.jan
Super User

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.

waclawek.jan
Super User

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

 

JW