2019-08-17 08:15 AM
Hi, I have a problem in DMA with stm32f4XX. I need to use two peripherals i2c3 for IMU and UART4 for gps, I setup the base code and its working fine when one of the peripheral DMA initialisation is disable.
Here is my code:-
void GPIO_I2C3_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
static DMA_HandleTypeDef hdma2_tx;
static DMA_HandleTypeDef hdma2_rx;
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_I2C3_CLK_ENABLE();
__HAL_RCC_I2C3_FORCE_RESET();
HAL_Delay(10);
__HAL_RCC_I2C3_RELEASE_RESET();
__HAL_RCC_DMA1_CLK_ENABLE();
GPIO_Init.Pin = GPIO_PIN_8;
GPIO_Init.Mode = GPIO_MODE_AF_OD;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_Init.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOA,&GPIO_Init);
GPIO_Init.Pin = GPIO_PIN_9;
GPIO_Init.Mode = GPIO_MODE_AF_OD;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_Init.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOC,&GPIO_Init);
i2c3_cfg.Instance = I2C3;
i2c3_cfg.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
i2c3_cfg.Init.ClockSpeed = 400000;
i2c3_cfg.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
i2c3_cfg.Init.DutyCycle = I2C_DUTYCYCLE_2;
i2c3_cfg.Init.GeneralCallMode = I2C_GENERALCALL_ENABLE;
i2c3_cfg.Init.OwnAddress1 = 0;
i2c3_cfg.Init.OwnAddress2 = 0;
i2c3_cfg.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
hdma2_tx.Instance = DMA1_Stream4;
hdma2_tx.Init.Channel = DMA_CHANNEL_3;
hdma2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma2_tx.Init.Mode = DMA_NORMAL;
hdma2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma2_tx.Init.MemBurst = DMA_MBURST_INC8;
hdma2_tx.Init.PeriphBurst = DMA_PBURST_INC8;
HAL_DMA_Init(&hdma2_tx);
__HAL_LINKDMA(&i2c3_cfg, hdmatx, hdma2_tx);
hdma2_rx.Instance = DMA1_Stream2;
hdma2_rx.Init.Channel = DMA_CHANNEL_3;
hdma2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma2_rx.Init.Mode = DMA_NORMAL;
hdma2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma2_rx.Init.MemBurst = DMA_MBURST_INC8;
hdma2_rx.Init.PeriphBurst = DMA_PBURST_INC8;
HAL_DMA_Init(&hdma2_rx);
__HAL_LINKDMA(&i2c3_cfg, hdmarx, hdma2_rx);
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
HAL_NVIC_SetPriority(I2C3_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C3_ER_IRQn);
HAL_NVIC_SetPriority(I2C3_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C3_EV_IRQn);
HAL_I2C_Init(&i2c3_cfg);
}
void GPIO_UART4_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
static DMA_HandleTypeDef hdma1_rx;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
GPIO_Init.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Mode = GPIO_MODE_AF_PP; //uart4 tx pin as pushpull
GPIO_Init.Alternate = GPIO_AF8_UART4;
GPIO_Init.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_Init);
GPS_Uart.Instance = UART4;
GPS_Uart.Init.BaudRate = 9600;
GPS_Uart.Init.StopBits = UART_STOPBITS_1;
GPS_Uart.Init.WordLength = UART_WORDLENGTH_8B;
GPS_Uart.Init.Mode = UART_MODE_TX_RX;
GPS_Uart.Init.Parity = UART_PARITY_NONE;
GPS_Uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
GPS_Uart.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&GPS_Uart);
hdma1_rx.Instance = DMA1_Stream2;
hdma1_rx.Init.Channel = DMA_CHANNEL_4;
hdma1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma1_rx.Init.Mode = DMA_CIRCULAR;
hdma1_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma1_rx.Init.MemBurst = DMA_MBURST_INC8;
hdma1_rx.Init.PeriphBurst = DMA_PBURST_INC8;
HAL_DMA_Init(&hdma1_rx);
__HAL_LINKDMA(&GPS_Uart, hdmarx, hdma1_rx);
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
__HAL_UART_ENABLE_IT(&GPS_Uart,UART_IT_IDLE);
__HAL_DMA_ENABLE_IT(&hdma1_rx,DMA_IT_TC);
}
and IRQs :-
void DMA1_Stream2_IRQHandler(void)
{
flag_g=~flag_g;
if(flag_g)
HAL_DMA_IRQHandler(i2c3_cfg.hdmarx);
else
HAL_DMA_IRQHandler(GPS_Uart.hdmarx); //UART4
}
void DMA1_Stream4_IRQHandler(void)
{
HAL_DMA_IRQHandler(i2c3_cfg.hdmatx);
}
void UART4_IRQHandler(void)
{
HAL_UART_IRQHandler(&GPS_Uart);
}
void I2C3_EV_IRQHandler(void)
{
HAL_I2C_EV_IRQHandler(&i2c3_cfg);
}
void I2C3_ER_IRQHandler(void)
{
HAL_I2C_ER_IRQHandler(&i2c3_cfg);
}
The main probleam is i2c3 and uart4 is in same dma stream-> dma_stream2, but in diffrent channel. So is there any way use two periphral with DMA which are in same stream?
2019-08-17 08:30 AM
There is no way. That is wy the DMAMUX in newer families comes handy.
2019-08-17 10:20 AM
You'll likely need to live with a simple UART4 RX interrupt handler.
Review if alternate pin muxing, or other usage might accommodate your needs.
2019-08-17 10:52 AM
Yes , right.
And it's working nice with simple uart interrupt. I wondering that while using dma transfer cmplt call back it's effting rtos timing, but with interrupt it's fine no latency.
2019-08-17 11:29 AM
Well for there to be any point of using DMA, you'd need a deeper buffer, and this might not cleanly align with data bursting from a GPS receiver.
2019-08-17 12:52 PM
I2C can be implemented by SW bit banging, and 400 kbps is easily done by SW.
USART is not, so just use DMA for this only exclusively.
The SW will be easier to maintain than acrobatically hop between 2 channels.