cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 I2C DMA ll, just sending once

Mfail.1
Associate II

Hey guys,

I am trying to get I2C working with DMA or without, but I am having similar issues with both.

The I2C sends out the data correctly the first time via DMA and the DMA_TC interrupt is called, however it gets never called again. I can also see this in my oscilloscope, it gets fired just once. However if I disconnect the sensor (MPU9250) and reconnect it again, it fires another time. Could it be, that I don't get an ACK bit.

My code:

void MX_I2C4_Init(void)
{
  LL_I2C_InitTypeDef I2C_InitStruct = {0};
 
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
  /**I2C4 GPIO Configuration  
  PF14   ------> I2C4_SCL
  PF15   ------> I2C4_SDA 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_14|LL_GPIO_PIN_15;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
  LL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
  /* Peripheral clock enable */
  LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_I2C4);
 
  /* I2C4 DMA Init */
  
  /* I2C4_TX Init */
  LL_BDMA_SetPeriphRequest(BDMA, LL_BDMA_CHANNEL_0, LL_DMAMUX2_REQ_I2C4_TX);
 
  LL_BDMA_SetDataTransferDirection(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_DIRECTION_MEMORY_TO_PERIPH);
 
  LL_BDMA_SetChannelPriorityLevel(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PRIORITY_LOW);
 
  LL_BDMA_SetMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MODE_NORMAL);
 
  LL_BDMA_SetPeriphIncMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PERIPH_NOINCREMENT);
 
  LL_BDMA_SetMemoryIncMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MEMORY_INCREMENT);
 
  LL_BDMA_SetPeriphSize(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PDATAALIGN_BYTE);
 
  LL_BDMA_SetMemorySize(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MDATAALIGN_BYTE);
 
  /* I2C4_RX Init */
  LL_BDMA_SetPeriphRequest(BDMA, LL_BDMA_CHANNEL_1, LL_DMAMUX2_REQ_I2C4_RX);
 
  LL_BDMA_SetDataTransferDirection(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_DIRECTION_PERIPH_TO_MEMORY);
 
  LL_BDMA_SetChannelPriorityLevel(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PRIORITY_LOW);
 
  LL_BDMA_SetMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MODE_NORMAL);
 
  LL_BDMA_SetPeriphIncMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PERIPH_NOINCREMENT);
 
  LL_BDMA_SetMemoryIncMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MEMORY_INCREMENT);
 
  LL_BDMA_SetPeriphSize(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PDATAALIGN_BYTE);
 
  LL_BDMA_SetMemorySize(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MDATAALIGN_BYTE);
 
  /* I2C4 interrupt Init */
  NVIC_SetPriority(I2C4_EV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(I2C4_EV_IRQn);
  NVIC_SetPriority(I2C4_ER_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(I2C4_ER_IRQn);
 
  /** I2C Initialization 
  */
  LL_I2C_EnableAutoEndMode(I2C4);
  LL_I2C_SetOwnAddress2(I2C4, 0, LL_I2C_OWNADDRESS2_NOMASK);
  LL_I2C_DisableOwnAddress2(I2C4);
  LL_I2C_DisableGeneralCall(I2C4);
  LL_I2C_EnableClockStretching(I2C4);
  I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  I2C_InitStruct.Timing = 0x00B03FDB;
  I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  I2C_InitStruct.DigitalFilter = 0;
  I2C_InitStruct.OwnAddress1 = 0;
  I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
 
  LL_I2C_Init(I2C4, &I2C_InitStruct);
 
  LL_DMA_EnablePeriphDMA(BDMA, LL_BDMA_CHANNEL_0);
  LL_DMA_EnablePeriphDMA(BDMA, LL_BDMA_CHANNEL_1);
 
  LL_BDMA_EnableIT_TC(BDMA, LL_BDMA_CHANNEL_0);
  LL_BDMA_EnableIT_TE(BDMA, LL_BDMA_CHANNEL_0);
  LL_BDMA_EnableIT_TC(BDMA, LL_BDMA_CHANNEL_1);
  LL_BDMA_EnableIT_TE(BDMA, LL_BDMA_CHANNEL_1);
 
  LL_I2C_EnableIT_NACK(I2C4);
  LL_I2C_EnableIT_STOP(I2C4);
  LL_I2C_EnableIT_TC(I2C4);
  LL_I2C_EnableIT_ADDR(I2C4);
  LL_I2C_EnableIT_ERR(I2C4);
  LL_I2C_EnableIT_TX(I2C4);
 
}
 
/* USER CODE BEGIN 1 */
__STATIC_INLINE void LL_DMA_EnablePeriphDMA(DMA_TypeDef *DMAx, uint32_t Stream)
{
	register uint32_t dma_base_addr = (uint32_t)DMAx;
 
	SET_BIT(((DMA_Stream_TypeDef *)(dma_base_addr + LL_DMA_STR_OFFSET_TAB[Stream]))->CR, DMA_SxCR_TRBUFF);
}
 
/* USER CODE END 1 */

and my sending function:

void i2c_mem_write(uint8_t addr, uint8_t reg, uint8_t* tx_data, uint16_t size){
 
	/* Set up for I2C */
	LL_I2C_EnableDMAReq_TX(I2C4);
	LL_DMA_EnablePeriphDMA(BDMA, LL_BDMA_CHANNEL_0);
 
	LL_I2C_SetMasterAddressingMode(I2C4, LL_I2C_ADDRESSING_MODE_7BIT);
	LL_I2C_SetSlaveAddr(I2C4, addr);
	LL_I2C_SetTransferRequest(I2C4, LL_I2C_REQUEST_WRITE);
	LL_I2C_SetTransferSize(I2C4, size+1);
	//LL_I2C_AcknowledgeNextData(I2C4, LL_I2C_ACK);
 
	/* transfer data to RAM section readable for BDMA*/
	txdata[0] = reg;
 
	for(int i= 0; i<size; i++){
		txdata[i+1] = tx_data[i];
	}
 
	/* Set up for BDMA */
	LL_BDMA_ConfigAddresses(BDMA,
							LL_BDMA_CHANNEL_0,
							(uint32_t)txdata,
							(uint32_t)&(I2C4->TXDR),
							LL_BDMA_DIRECTION_MEMORY_TO_PERIPH);
 
	LL_BDMA_SetDataLength(BDMA, LL_BDMA_CHANNEL_0, size+1);
 
 
 
	/* Start Transmission */
	LL_I2C_GenerateStartCondition(I2C4);
 
	//LL_I2C_TransmitData8(I2C4, 0x55);
	while(!LL_I2C_IsActiveFlag_BUSY(I2C4));
	LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_0);
	HAL_Delay(10);
	LL_I2C_GenerateStopCondition(I2C4);
 
//	if(LL_I2C_IsActiveFlag_BUSY(I2C4) == 1){
//		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
//	}
}

I cleared the stop flag and the DMA_TC flag in the according interrupt.

I am very new to this. So please be kind with me

0 REPLIES 0