2020-07-19 08:30 AM
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