2025-01-03 12:47 PM
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
2025-01-04 07:35 AM
__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.
2025-01-05 05:04 AM
You may want to read the explanation to GPDMA_CxSR.FIFOL in the GPDMA chapter of RM0481.
JW
2025-01-05 09:07 AM
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.
The problem I have now is that the HAL lib resets the fifo before calling the abort callback ...
I will try moving the call of the callback up to line 1000.