cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f072rb nucleo DMA for I2C and USART

nilsminor
Associate
Posted on October 15, 2016 at 20:22

Hi there,

i am struggling a bit by using my STM32f072rb nucleo to run it as an I2C1 Master sending and receiving via DMA. At the same time I am using USART1 to print over serial com port. For that i am using I2C1 and DMA channels 2 and 3, for USART1 I am using channels 4 and 5. USART is working :), and I2C works in non DMA mode, so i can see the Slave is acking the master when I search for it, but i really need to get I2C running over DMA. So when i reset the board it works for one time, what could be the problem for that? What have i done wrong with the DMA config?

void PSOM_i2c_init (void) {
I2cHandle.Instance = I2C1; //Schnittstelle I2C1
I2cHandle.Init.Timing = 0x00A51314; //Timingwert für I2C
I2cHandle.Init.OwnAddress1 = 0xA1; //Eigene Adresse
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; //7Bit Adressierungsmodus
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; //Keine Dualadressnutzung
I2cHandle.Init.OwnAddress2 = 0xA1; 
I2cHandle.Init.OwnAddress2Masks = 0;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; //Kein Gerneralcall 
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_ENABLED; //Aktiviere Nostretch
HAL_I2CEx_ConfigAnalogFilter(&I2cHandle, I2C_ANALOGFILTER_ENABLE);
if (HAL_I2C_Init(&I2cHandle) != HAL_OK) { //Rufe Init Funktion auf --> diese Ruft unter anderem die HAL_I2C_MspInit();
//If not HAL_OK then activate LED2
Error_Handler();
}
}

void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { 
GPIO_InitTypeDef GPIO_InitStruct;
static DMA_HandleTypeDef hdma_i2c_tx;
static DMA_HandleTypeDef hdma_i2c_rx;
RCC_PeriphCLKInitTypeDef RCC_PeripCLKInitStruct; //set clock
/*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
RCC_PeripCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
RCC_PeripCLKInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
HAL_RCCEx_GetPeriphCLKConfig(&RCC_PeripCLKInitStruct);
//Enable the GPIO-clock
__HAL_RCC_GPIOB_CLK_ENABLE();//__GPIOB_CLK_ENABLE();
//Enable the I2C-Clock
__HAL_RCC_I2C1_CLK_ENABLE();//__I2C1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMAx clock 
//Configure GPIOB Pin_8 as SCL for I2C
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //init GPIOB PIN8 (SCL-Pin)
//Configure GPIOB Pin_9 as SDA for USART
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //init GPIOB PIN9 (SDA-Pin)
/*##-4- Configure the DMA Channels #########################################*/
/* Configure the DMA handler for Transmission process */
hdma_i2c_tx.Instance = DMA1_Channel2;
hdma_i2c_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c_tx.Init.Mode = DMA_NORMAL;
hdma_i2c_tx.Init.Priority = DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_i2c_tx); 
__HAL_LINKDMA(hi2c, hdmatx, hdma_i2c_tx); /* Associate the initialized DMA handle to the the I2C handle */
/* Configure the DMA handler for Transmission process */
hdma_i2c_rx.Instance = DMA1_Channel3;
hdma_i2c_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c_rx.Init.Mode = DMA_NORMAL;
hdma_i2c_rx.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_i2c_rx);
__HAL_LINKDMA(hi2c, hdmarx, hdma_i2c_rx); /* Associate the initialized DMA handle to the the I2C handle */
/*##-5- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt (I2Cx_TX) */
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
/* NVIC configuration for DMA transfer complete interrupt (I2Cx_RX) */
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0); 
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
/*##-6- Configure the NVIC for I2C ########################################*/ 
HAL_NVIC_SetPriority(I2C1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(I2C1_IRQn);
}
void I2C1_Handler(void) {
//Call Hal_I2C_EventHandler
HAL_I2C_EV_IRQHandler(&I2cHandle); //Eventhandler - Dieser kümmert sich automatisch um das erzeugen von Startconditions, ACKs, NACKs, Stopbits und Stopcondition
HAL_I2C_ER_IRQHandler(&I2cHandle); //Errorhandler
}
void DMA1_Channel2_3_IRQHandler(void)
{
HAL_DMA_IRQHandler(I2cHandle.hdmatx); 
HAL_DMA_IRQHandler(I2cHandle.hdmarx);
}

void HAL_UART_MspInit (UART_HandleTypeDef* huart) {
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==USART1)
{
__USART1_CLK_ENABLE(); /* Peripheral clock enable */
/* USART1 GPIO Configuration 
PA9 ------> USART1_TX
PA10 ------> USART1_RX */
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA channels 4 & 5 init*/
hdma_usart1_rx.Instance = DMA1_Channel4; 
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_DISABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_usart1_rx);
__HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
hdma_usart1_tx.Instance = DMA1_Channel5;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_DISABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_usart1_tx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_usart1_tx);
__HAL_LINKDMA(huart,hdmatx, hdma_usart1_tx);
/* System interrupt init*/
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}

#stm32f0-art-unart-i2c-dma
1 REPLY 1
Nesrine M_O
Lead II
Posted on October 31, 2016 at 15:11

Hi minor.nils,

I recommend you to have a look to this example under the STM32CUBE F0 package, it may be helpful:

•STM32Cube_FW_F0_V1.6.0\Projects\STM32F072RB-Nucleo\Examples\I2C\I2C_TwoBoards_ComDMA: This example describes how to perform I2C data buffer transmission/reception between two boards, via DMA.

-Syrine-