cancel
Showing results for 
Search instead for 
Did you mean: 

DMA data Reception from I2C

SA  V.1
Senior

Hello Community, Am interfacing LIS2DTW12 Acceleration Sensor with STM NucleoL476RGT6U by I2C communication protocal in  blocking mode working everything fine. But i want collect data in non blocking mode so collecting data to DMA and implementing the custom callback but control not coming to custom call back (custom callback was not triggered ) if i stop the program data will present in the Data array .
While Debugging DMA transfer complete interrupt triggered succesfully when going to handle DMA_IRQ Handler during that time am check the I2C state thats still HAL_I2C_STATE_BUSY_RX Whats the issue ?
if i forcefully Change the I2C state to ready and forcefully call the custom implemented callback then it will work .May i know Whats happening whats the issue is from hardware side or software ?Anyone helpme to resolve this ....

MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
SensorLIS2DTW12Acc_init();
start_dma_read();

void SensorLIS2DTW12Acc_init(void) {
// Read the WHO_AM_I register to verify communication with the LIS2DTW12
Ret = HAL_I2C_Mem_Read(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_WHO_AM_I, I2C_MEMADD_SIZE_8BIT, &reg_data, 1, HAL_MAX_DELAY);

ctrl1Data = LIS2DTW12_ODR_HP_MODE;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_CTRL1, I2C_MEMADD_SIZE_8BIT, &ctrl1Data, 1, HAL_MAX_DELAY);

ctrl6Data = g_Selection;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_CTRL6, I2C_MEMADD_SIZE_8BIT, &ctrl6Data, 1, HAL_MAX_DELAY);

fifoctrl = LIS2DTW12_CONTI_MODE_FTH_LEVEL;
HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDR_LIS2DTW12, LIS2DTW12_FIFO_CTRL, I2C_MEMADD_SIZE_8BIT, &fifoctrl, 1, HAL_MAX_DELAY);
}

void start_dma_read(void) {
// Send the register address to read from (OUT_X_L)
if (HAL_I2C_Master_Transmit(&hi2c1, SLAVE_ADDR_LIS2DTW12, &reg_addr, 1, HAL_MAX_DELAY) == HAL_OK) {
// Start DMA reception (6 bytes for X, Y, Z)
if (HAL_I2C_Master_Receive_DMA(&hi2c1, SLAVE_ADDR_LIS2DTW12, accel_data, sizeof(accel_data)) == HAL_OK) {
} }}

Control stuck inside of  bellow program .....

/* Transfer Complete Interrupt management ***********************************/
else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
{
// printf("DMA TC Interrupt, I2C State: 0x%X\n", hi2c1.State);  
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
/* Disable the transfer complete and error interrupt */
/* if the DMA mode is not CIRCULAR */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);

/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
/* Clear the transfer complete flag */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1CU));

/* Process Unlocked */
__HAL_UNLOCK(hdma);

if (hdma->XferCpltCallback != NULL)
{
printf("Calling XferCpltCallback: %p\n", hdma->XferCpltCallback);
hi2c1.XferCount = 0; // Force XferCount to 0
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
hi2c1.Instance->CR2 |= I2C_CR2_STOP;         // These lines of codes are inserted manually to check?
while (hi2c1.Instance->ISR & I2C_ISR_BUSY);
hi2c1.Instance->ICR = I2C_ICR_STOPCF;
hi2c1.State = HAL_I2C_STATE_READY;
HAL_I2C_MasterRxCpltCallback(&hi2c1); // Forced callback
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
if (hi2c->Instance == I2C1) {
dmaTransferComplete = 1;
printf("Rx Callback! State: 0x%X, Error: 0x%lX\n", hi2c->State, hi2c->ErrorCode);
int16_t x = (int16_t)(accel_data[1] << 8 | accel_data[0]);
printf("X: %d\n", x);
hi2c->State = HAL_I2C_STATE_READY; // Ensure state is reset
start_dma_read();
}
}   

1 ACCEPTED SOLUTION

Accepted Solutions
SA  V.1
Senior
Chensie
Associate II
 

‎2017-01-19 5:36 PM

Posted on January 20, 2017 at 02:36

Hello,

When you use DMA with I2C to Transmit or Receive data,  you should 

Enable I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts.

because they all called I2C_DMAXferCplt (hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt)

and it  enable interrupt call to handle I2C state.

 

  __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);

 

This is the solution for my prolem . Before i Didn't Enabled the I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts so my callback function was not triggering After enabling these 2 interrupts now triggering .

View solution in original post

1 REPLY 1
SA  V.1
Senior
Chensie
Associate II
 

‎2017-01-19 5:36 PM

Posted on January 20, 2017 at 02:36

Hello,

When you use DMA with I2C to Transmit or Receive data,  you should 

Enable I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts.

because they all called I2C_DMAXferCplt (hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt)

and it  enable interrupt call to handle I2C state.

 

  __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);

 

This is the solution for my prolem . Before i Didn't Enabled the I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts so my callback function was not triggering After enabling these 2 interrupts now triggering .