Building Board Support Package (BSP) for STM32F411-Nucleo64 Part13.2: DMA Memory to Memory Mode

In this second section of the thirteenth part of board support package, we shall develop the source code of the DMA driver and test the driver with Memory to Memory mode.

In this guide, we shall cover the following:

  • Adding the required functions to the header file.
  • Develop the source code.
  • DMA Memory to Memory driver.
  • Code.
  • Results.

1. Adding the required function to the header file:

Open dma_bsp.h header file and add the following three functions:

First function:

void BSP_DMA_Init(DMA_Stream_TypeDef *dma, DMA_ConfigTypedef *config );

This function shall initialize the DMA and takes DMA_Stream_TypeDef and DMA_ConfigTypedef as argument and returns nothing.

Second and third function as following:

void BSP_DMA_Transfer_Single_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest, uint16_t len);

void BSP_DMA_Transfer_Double_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest1,uint32_t dest2, uint16_t len);

Those functions will launch DMA transfer for both single and double buffer mode.

Both functions will take DMA_Stream_TypeDef, length and source as argument.

In double buffer, you will have two destinations rather than single destination for single buffer transfer.

Hence, the updated header file as following:

#ifndef DMA_BSP_H_
#define DMA_BSP_H_

#include "stm32f4xx.h"
#include "stdint.h"


#define __BSP_DMA1__CLOCK_ENABLE()		RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN;
#define __BSP_DMA2__CLOCK_ENABLE()		RCC->AHB1ENR|=RCC_AHB1ENR_DMA2EN;



typedef enum
{
	dma1stream0=0,
	dma1stream1,
	dma1stream2,
	dma1stream3,
	dma1stream4,
	dma1stream5,
	dma1stream6,
	dma1stream7,

	dma2stream0,
	dma2stream1,
	dma2stream2,
	dma2stream3,
	dma2stream4,
	dma2stream5,
	dma2stream6,
	dma2stream7,

}DMAStreamTypedef;


typedef enum
{
	Channel0=0,
	Channel1,
	Channel2,
	Channel3,
	Channel4,
	Channel5,
	Channel6,
	Channel7
}DMA_Stream_ChannelTypedef;



typedef enum
{
	singleTransfer=0,
	INCR4,
	INCR8,
	INCR16,
}DMA_Stream_BurstTypedef;


typedef enum
{
	singleBuffer=0,
	doubleBuffer,
}DMA_StreamDoubleBufferTypedef;

typedef enum
{
	low=0,
	medium,
	high,
	very_high

}DMA_StreamPriorityTypedef;

typedef enum
{
	Psize=0,
	wordSize,
}DMA_StreamPrephIncSizeTypedef;


typedef enum
{
	byte=0,
	halfWord,
	word

}DMA_SizeTypedef;

typedef enum
{
	fixedMode=0,
	incMode=1
}DMA_IncModeTypedef;


typedef enum
{
	SingleTransfer=0,
	Circular=1
}DMA_CricularTypedef;


typedef enum
{
	peripheral2Memory=0,
	memory2Peripheral,
	memory2Memory

}DMA_DirectionTypedef;


typedef enum
{
	DMAController=0,
	PeripheralController,
}DMAPeripheralControlTypedef;


typedef enum
{
	InterruptDisabled=0,
	InterruptEnbaled=1,

	TransferComplet=1,
	HalfTransfer=1,
	TransferError=1,
	DirectModeError=1
}DMA_InterruptTypedef;

typedef struct
{

	uint8_t DMA_Channel;
	uint8_t PeripheralBurstMode;
	uint8_t MemoryBurstMode;
	uint8_t DoubleBuffer;
	uint8_t Priority;
	uint8_t PeripheralIncSize;
	uint8_t MemorySize;
	uint8_t PerpheralSize;
	uint8_t MemoryIncMode;
	uint8_t PeripheralIncMode;
	uint8_t CircularMode;
	uint8_t Direction;
	uint8_t PeripheralController;
	uint8_t InterruptEnable;
	uint8_t DMAStream;
	uint8_t TransferCompleteInterrupt;
	uint8_t HalfTransferInterrupt;
	uint8_t TransferErrorInterrupt;
	uint8_t DirectModeErrorInterrupt;
}DMA_ConfigTypedef;

void BSP_DMA_Init(DMA_Stream_TypeDef *dma, DMA_ConfigTypedef *config );

void BSP_DMA_Transfer_Single_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest, uint16_t len);

void BSP_DMA_Transfer_Double_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest1,uint32_t dest2, uint16_t len);


#endif /* DMA_BSP_H_ */

2. Develop the source code:

We start off by creating new source code with name of dma_bsp.c.

Within the source code, we shall the following header file:

#include "dma_bsp.h"

We start with DMA Initialization:

void BSP_DMA_Init(DMA_Stream_TypeDef *dma, DMA_ConfigTypedef *config )

Make sure that the DMA stream is disabled:

	/*Disable the stream*/
	dma->CR &=~ DMA_SxCR_EN;
	/*Wait until stream is disabled*/
	while ((dma->CR& DMA_SxCR_EN));

Reset the control register:

dma->CR=0;

Configure the DMA according to the passed parameters as following:

dma->CR |=(config->DMA_Channel << DMA_SxCR_CHSEL_Pos);

	dma->CR |=(config->PeripheralBurstMode<<DMA_SxCR_PBURST_Pos);

	dma->CR|=(config->MemoryBurstMode<<DMA_SxCR_MBURST_Pos);

	dma->CR|=(config->DoubleBuffer<<DMA_SxCR_DBM_Pos);

	dma->CR|=(config->Priority<<DMA_SxCR_PL_Pos);

	dma->CR|=(config->MemorySize<<DMA_SxCR_MSIZE_Pos);

	dma->CR|=(config->PerpheralSize<<DMA_SxCR_PSIZE_Pos);

	dma->CR|= (config->MemoryIncMode<<DMA_SxCR_MINC_Pos);

	dma->CR|= (config->PeripheralIncMode<<DMA_SxCR_PINC_Pos);

	dma->CR|=(config->CircularMode<<DMA_SxCR_CIRC_Pos);

	dma->CR|=(config->Direction<<DMA_SxCR_DIR_Pos);

	if(config->Direction==memory2Memory)
	{
		dma->FCR|=(1U<<DMA_SxFCR_DMDIS_Pos);
	}

	dma->CR|=(config->PeripheralController<<DMA_SxCR_PFCTRL_Pos);

	if(config->InterruptEnable==InterruptEnbaled)
	{

		switch (config->DMAStream)
		{

		case dma1stream0 : NVIC_EnableIRQ(DMA1_Stream0_IRQn); break;
		case dma1stream1 : NVIC_EnableIRQ(DMA1_Stream1_IRQn); break;
		case dma1stream2 : NVIC_EnableIRQ(DMA1_Stream2_IRQn); break;
		case dma1stream3 : NVIC_EnableIRQ(DMA1_Stream3_IRQn); break;
		case dma1stream4 : NVIC_EnableIRQ(DMA1_Stream4_IRQn); break;
		case dma1stream5 : NVIC_EnableIRQ(DMA1_Stream5_IRQn); break;
		case dma1stream6 : NVIC_EnableIRQ(DMA1_Stream6_IRQn); break;
		case dma1stream7 : NVIC_EnableIRQ(DMA1_Stream7_IRQn); break;

		case dma2stream0 : NVIC_EnableIRQ(DMA2_Stream0_IRQn); break;
		case dma2stream1 : NVIC_EnableIRQ(DMA2_Stream1_IRQn); break;
		case dma2stream2 : NVIC_EnableIRQ(DMA2_Stream2_IRQn); break;
		case dma2stream3 : NVIC_EnableIRQ(DMA2_Stream3_IRQn); break;
		case dma2stream4 : NVIC_EnableIRQ(DMA2_Stream4_IRQn); break;
		case dma2stream5 : NVIC_EnableIRQ(DMA2_Stream5_IRQn); break;
		case dma2stream6 : NVIC_EnableIRQ(DMA2_Stream6_IRQn); break;
		case dma2stream7 : NVIC_EnableIRQ(DMA2_Stream7_IRQn); break;

		default: break;


		}

	}

	dma->CR|=(config->TransferCompleteInterrupt<<DMA_SxCR_TCIE_Pos);

	dma->CR|=(config->HalfTransferInterrupt<<DMA_SxCR_HTIE_Pos);

	dma->CR|=(config->TransferErrorInterrupt<<DMA_SxCR_TEIE_Pos);

	dma->CR|=(config->DirectModeErrorInterrupt<<DMA_SxCR_DMEIE_Pos);

For DMA transfer single buffer:

void BSP_DMA_Transfer_Single_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest, uint16_t len)
{
	dma->M0AR=dest;
	dma->PAR=src;
	dma->NDTR=len;
	dma->CR |=DMA_SxCR_EN;
}

For double buffer mode:

void BSP_DMA_Transfer_Double_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest1,uint32_t dest2, uint16_t len)
{
	dma->M0AR=(uint32_t)dest1;
	dma->M1AR=(uint32_t)dest2;
	dma->PAR=(uint32_t)src;
	dma->NDTR=len;
	dma->CR |=DMA_SxCR_EN;
}

For the interrupt handler:

__WEAK void DMA1_Stream0_handler(void)
{}
__WEAK void DMA1_Stream1_handler(void)
{}
__WEAK void DMA1_Stream2_handler(void)
{}
__WEAK void DMA1_Stream3_handler(void)
{}
__WEAK void DMA1_Stream4_handler(void)
{}
__WEAK void DMA1_Stream5_handler(void)
{}
__WEAK void DMA1_Stream6_handler(void)
{}
__WEAK void DMA1_Stream7_handler(void)
{}

__WEAK void DMA2_Stream0_handler(void)
{}
__WEAK void DMA2_Stream1_handler(void)
{}
__WEAK void DMA2_Stream2_handler(void)
{}
__WEAK void DMA2_Stream3_handler(void)
{}
__WEAK void DMA2_Stream4_handler(void)
{}
__WEAK void DMA2_Stream5_handler(void)
{}
__WEAK void DMA2_Stream6_handler(void)
{}
__WEAK void DMA2_Stream7_handler(void)
{}


void DMA1_Stream0_IRQHandler(void)
{
	/*Call DMA handler*/
	DMA1_Stream0_handler();
	/*Clear interrupt flags*/
	DMA1->LIFCR=DMA_LIFCR_CFEIF0;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF0;
	DMA1->LIFCR=DMA_LIFCR_CTEIF0;
	DMA1->LIFCR=DMA_LIFCR_CHTIF0;
	DMA1->LIFCR=DMA_LIFCR_CTCIF0;



}

void DMA1_Stream1_IRQHandler(void)
{
	DMA1_Stream1_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF1;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF1;
	DMA1->LIFCR=DMA_LIFCR_CTEIF1;
	DMA1->LIFCR=DMA_LIFCR_CHTIF1;
	DMA1->LIFCR=DMA_LIFCR_CTCIF1;
}
void DMA1_Stream2_IRQHandler(void)
{
	DMA1_Stream2_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF2;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF2;
	DMA1->LIFCR=DMA_LIFCR_CTEIF2;
	DMA1->LIFCR=DMA_LIFCR_CHTIF2;
	DMA1->LIFCR=DMA_LIFCR_CTCIF2;
}
void DMA1_Stream3_IRQHandler(void)
{
	DMA1_Stream3_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF3;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF3;
	DMA1->LIFCR=DMA_LIFCR_CTEIF3;
	DMA1->LIFCR=DMA_LIFCR_CHTIF3;
	DMA1->LIFCR=DMA_LIFCR_CTCIF3;
}
void DMA1_Stream4_IRQHandler(void)
{
	DMA1_Stream4_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF4;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF4;
	DMA1->HIFCR=DMA_HIFCR_CTEIF4;
	DMA1->HIFCR=DMA_HIFCR_CHTIF4;
	DMA1->HIFCR=DMA_HIFCR_CTCIF4;
}
void DMA1_Stream5_IRQHandler(void)
{
	DMA1_Stream5_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF5;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF5;
	DMA1->HIFCR=DMA_HIFCR_CTEIF5;
	DMA1->HIFCR=DMA_HIFCR_CHTIF5;
	DMA1->HIFCR=DMA_HIFCR_CTCIF5;
}

void DMA1_Stream6_IRQHandler(void)
{
	DMA1_Stream6_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF6;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF6;
	DMA1->HIFCR=DMA_HIFCR_CTEIF6;
	DMA1->HIFCR=DMA_HIFCR_CHTIF6;
	DMA1->HIFCR=DMA_HIFCR_CTCIF6;
}
void DMA1_Stream7_IRQHandler(void)
{
	DMA1_Stream7_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF7;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF7;
	DMA1->HIFCR=DMA_HIFCR_CTEIF7;
	DMA1->HIFCR=DMA_HIFCR_CHTIF7;
	DMA1->HIFCR=DMA_HIFCR_CTCIF7;
}


void DMA2_Stream0_IRQHandler(void)
{
	DMA2_Stream0_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF0;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF0;
	DMA2->LIFCR=DMA_LIFCR_CTEIF0;
	DMA2->LIFCR=DMA_LIFCR_CHTIF0;
	DMA2->LIFCR=DMA_LIFCR_CTCIF0;
}

void DMA2_Stream1_IRQHandler(void)
{
	DMA2_Stream1_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF1;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF1;
	DMA2->LIFCR=DMA_LIFCR_CTEIF1;
	DMA2->LIFCR=DMA_LIFCR_CHTIF1;
	DMA2->LIFCR=DMA_LIFCR_CTCIF1;
}
void DMA2_Stream2_IRQHandler(void)
{
	DMA2_Stream2_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF2;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF2;
	DMA2->LIFCR=DMA_LIFCR_CTEIF2;
	DMA2->LIFCR=DMA_LIFCR_CHTIF2;
	DMA2->LIFCR=DMA_LIFCR_CTCIF2;
}
void DMA2_Stream3_IRQHandler(void)
{
	DMA2_Stream3_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF3;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF3;
	DMA2->LIFCR=DMA_LIFCR_CTEIF3;
	DMA2->LIFCR=DMA_LIFCR_CHTIF3;
	DMA2->LIFCR=DMA_LIFCR_CTCIF3;
}
void DMA2_Stream4_IRQHandler(void)
{
	DMA2_Stream4_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF4;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF4;
	DMA2->HIFCR=DMA_HIFCR_CTEIF4;
	DMA2->HIFCR=DMA_HIFCR_CHTIF4;
	DMA2->HIFCR=DMA_HIFCR_CTCIF4;
}

void DMA2_Stream5_IRQHandler(void)
{
	DMA2_Stream5_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF5;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF5;
	DMA2->HIFCR=DMA_HIFCR_CTEIF5;
	DMA2->HIFCR=DMA_HIFCR_CHTIF5;
	DMA2->HIFCR=DMA_HIFCR_CTCIF5;
}

void DMA2_Stream6_IRQHandler(void)
{
	DMA2_Stream6_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF6;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF6;
	DMA2->HIFCR=DMA_HIFCR_CTEIF6;
	DMA2->HIFCR=DMA_HIFCR_CHTIF6;
	DMA2->HIFCR=DMA_HIFCR_CTCIF6;
}
void DMA2_Stream7_IRQHandler(void)
{
	DMA2_Stream7_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF7;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF7;
	DMA2->HIFCR=DMA_HIFCR_CTEIF7;
	DMA2->HIFCR=DMA_HIFCR_CHTIF7;
	DMA2->HIFCR=DMA_HIFCR_CTCIF7;
}

The process as following:

Call the interrupt handler which is defined as weak function that will allow the user to overwrite the function then clear the pending flags.

Hence, the entire source code as following:

#include "dma_bsp.h"

void BSP_DMA_Init(DMA_Stream_TypeDef *dma, DMA_ConfigTypedef *config )
{
	/*Disable the stream*/
	dma->CR &=~ DMA_SxCR_EN;
	/*Wait until stream is disabled*/
	while ((dma->CR& DMA_SxCR_EN));

	dma->CR=0;

	dma->CR |=(config->DMA_Channel << DMA_SxCR_CHSEL_Pos);

	dma->CR |=(config->PeripheralBurstMode<<DMA_SxCR_PBURST_Pos);

	dma->CR|=(config->MemoryBurstMode<<DMA_SxCR_MBURST_Pos);

	dma->CR|=(config->DoubleBuffer<<DMA_SxCR_DBM_Pos);

	dma->CR|=(config->Priority<<DMA_SxCR_PL_Pos);

	dma->CR|=(config->MemorySize<<DMA_SxCR_MSIZE_Pos);

	dma->CR|=(config->PerpheralSize<<DMA_SxCR_PSIZE_Pos);

	dma->CR|= (config->MemoryIncMode<<DMA_SxCR_MINC_Pos);

	dma->CR|= (config->PeripheralIncMode<<DMA_SxCR_PINC_Pos);

	dma->CR|=(config->CircularMode<<DMA_SxCR_CIRC_Pos);

	dma->CR|=(config->Direction<<DMA_SxCR_DIR_Pos);

	if(config->Direction==memory2Memory)
	{
		dma->FCR|=(1U<<DMA_SxFCR_DMDIS_Pos);
	}

	dma->CR|=(config->PeripheralController<<DMA_SxCR_PFCTRL_Pos);

	if(config->InterruptEnable==InterruptEnbaled)
	{

		switch (config->DMAStream)
		{

		case dma1stream0 : NVIC_EnableIRQ(DMA1_Stream0_IRQn); break;
		case dma1stream1 : NVIC_EnableIRQ(DMA1_Stream1_IRQn); break;
		case dma1stream2 : NVIC_EnableIRQ(DMA1_Stream2_IRQn); break;
		case dma1stream3 : NVIC_EnableIRQ(DMA1_Stream3_IRQn); break;
		case dma1stream4 : NVIC_EnableIRQ(DMA1_Stream4_IRQn); break;
		case dma1stream5 : NVIC_EnableIRQ(DMA1_Stream5_IRQn); break;
		case dma1stream6 : NVIC_EnableIRQ(DMA1_Stream6_IRQn); break;
		case dma1stream7 : NVIC_EnableIRQ(DMA1_Stream7_IRQn); break;

		case dma2stream0 : NVIC_EnableIRQ(DMA2_Stream0_IRQn); break;
		case dma2stream1 : NVIC_EnableIRQ(DMA2_Stream1_IRQn); break;
		case dma2stream2 : NVIC_EnableIRQ(DMA2_Stream2_IRQn); break;
		case dma2stream3 : NVIC_EnableIRQ(DMA2_Stream3_IRQn); break;
		case dma2stream4 : NVIC_EnableIRQ(DMA2_Stream4_IRQn); break;
		case dma2stream5 : NVIC_EnableIRQ(DMA2_Stream5_IRQn); break;
		case dma2stream6 : NVIC_EnableIRQ(DMA2_Stream6_IRQn); break;
		case dma2stream7 : NVIC_EnableIRQ(DMA2_Stream7_IRQn); break;

		default: break;


		}

	}

	dma->CR|=(config->TransferCompleteInterrupt<<DMA_SxCR_TCIE_Pos);

	dma->CR|=(config->HalfTransferInterrupt<<DMA_SxCR_HTIE_Pos);

	dma->CR|=(config->TransferErrorInterrupt<<DMA_SxCR_TEIE_Pos);

	dma->CR|=(config->DirectModeErrorInterrupt<<DMA_SxCR_DMEIE_Pos);


}

void BSP_DMA_Transfer_Single_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest, uint16_t len)
{
	dma->M0AR=dest;
	dma->PAR=src;
	dma->NDTR=len;
	dma->CR |=DMA_SxCR_EN;
}

void BSP_DMA_Transfer_Double_Buffer(DMA_Stream_TypeDef *dma, uint32_t src, uint32_t dest1,uint32_t dest2, uint16_t len)
{
	dma->M0AR=(uint32_t)dest1;
	dma->M1AR=(uint32_t)dest2;
	dma->PAR=(uint32_t)src;
	dma->NDTR=len;
	dma->CR |=DMA_SxCR_EN;
}


__WEAK void DMA1_Stream0_handler(void)
{}
__WEAK void DMA1_Stream1_handler(void)
{}
__WEAK void DMA1_Stream2_handler(void)
{}
__WEAK void DMA1_Stream3_handler(void)
{}
__WEAK void DMA1_Stream4_handler(void)
{}
__WEAK void DMA1_Stream5_handler(void)
{}
__WEAK void DMA1_Stream6_handler(void)
{}
__WEAK void DMA1_Stream7_handler(void)
{}

__WEAK void DMA2_Stream0_handler(void)
{}
__WEAK void DMA2_Stream1_handler(void)
{}
__WEAK void DMA2_Stream2_handler(void)
{}
__WEAK void DMA2_Stream3_handler(void)
{}
__WEAK void DMA2_Stream4_handler(void)
{}
__WEAK void DMA2_Stream5_handler(void)
{}
__WEAK void DMA2_Stream6_handler(void)
{}
__WEAK void DMA2_Stream7_handler(void)
{}


void DMA1_Stream0_IRQHandler(void)
{
	/*Call DMA handler*/
	DMA1_Stream0_handler();
	/*Clear interrupt flags*/
	DMA1->LIFCR=DMA_LIFCR_CFEIF0;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF0;
	DMA1->LIFCR=DMA_LIFCR_CTEIF0;
	DMA1->LIFCR=DMA_LIFCR_CHTIF0;
	DMA1->LIFCR=DMA_LIFCR_CTCIF0;



}

void DMA1_Stream1_IRQHandler(void)
{
	DMA1_Stream1_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF1;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF1;
	DMA1->LIFCR=DMA_LIFCR_CTEIF1;
	DMA1->LIFCR=DMA_LIFCR_CHTIF1;
	DMA1->LIFCR=DMA_LIFCR_CTCIF1;
}
void DMA1_Stream2_IRQHandler(void)
{
	DMA1_Stream2_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF2;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF2;
	DMA1->LIFCR=DMA_LIFCR_CTEIF2;
	DMA1->LIFCR=DMA_LIFCR_CHTIF2;
	DMA1->LIFCR=DMA_LIFCR_CTCIF2;
}
void DMA1_Stream3_IRQHandler(void)
{
	DMA1_Stream3_handler();

	DMA1->LIFCR=DMA_LIFCR_CFEIF3;
	DMA1->LIFCR=DMA_LIFCR_CDMEIF3;
	DMA1->LIFCR=DMA_LIFCR_CTEIF3;
	DMA1->LIFCR=DMA_LIFCR_CHTIF3;
	DMA1->LIFCR=DMA_LIFCR_CTCIF3;
}
void DMA1_Stream4_IRQHandler(void)
{
	DMA1_Stream4_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF4;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF4;
	DMA1->HIFCR=DMA_HIFCR_CTEIF4;
	DMA1->HIFCR=DMA_HIFCR_CHTIF4;
	DMA1->HIFCR=DMA_HIFCR_CTCIF4;
}
void DMA1_Stream5_IRQHandler(void)
{
	DMA1_Stream5_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF5;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF5;
	DMA1->HIFCR=DMA_HIFCR_CTEIF5;
	DMA1->HIFCR=DMA_HIFCR_CHTIF5;
	DMA1->HIFCR=DMA_HIFCR_CTCIF5;
}

void DMA1_Stream6_IRQHandler(void)
{
	DMA1_Stream6_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF6;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF6;
	DMA1->HIFCR=DMA_HIFCR_CTEIF6;
	DMA1->HIFCR=DMA_HIFCR_CHTIF6;
	DMA1->HIFCR=DMA_HIFCR_CTCIF6;
}
void DMA1_Stream7_IRQHandler(void)
{
	DMA1_Stream7_handler();

	DMA1->HIFCR=DMA_HIFCR_CFEIF7;
	DMA1->HIFCR=DMA_HIFCR_CDMEIF7;
	DMA1->HIFCR=DMA_HIFCR_CTEIF7;
	DMA1->HIFCR=DMA_HIFCR_CHTIF7;
	DMA1->HIFCR=DMA_HIFCR_CTCIF7;
}


void DMA2_Stream0_IRQHandler(void)
{
	DMA2_Stream0_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF0;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF0;
	DMA2->LIFCR=DMA_LIFCR_CTEIF0;
	DMA2->LIFCR=DMA_LIFCR_CHTIF0;
	DMA2->LIFCR=DMA_LIFCR_CTCIF0;
}

void DMA2_Stream1_IRQHandler(void)
{
	DMA2_Stream1_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF1;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF1;
	DMA2->LIFCR=DMA_LIFCR_CTEIF1;
	DMA2->LIFCR=DMA_LIFCR_CHTIF1;
	DMA2->LIFCR=DMA_LIFCR_CTCIF1;
}
void DMA2_Stream2_IRQHandler(void)
{
	DMA2_Stream2_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF2;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF2;
	DMA2->LIFCR=DMA_LIFCR_CTEIF2;
	DMA2->LIFCR=DMA_LIFCR_CHTIF2;
	DMA2->LIFCR=DMA_LIFCR_CTCIF2;
}
void DMA2_Stream3_IRQHandler(void)
{
	DMA2_Stream3_handler();

	DMA2->LIFCR=DMA_LIFCR_CFEIF3;
	DMA2->LIFCR=DMA_LIFCR_CDMEIF3;
	DMA2->LIFCR=DMA_LIFCR_CTEIF3;
	DMA2->LIFCR=DMA_LIFCR_CHTIF3;
	DMA2->LIFCR=DMA_LIFCR_CTCIF3;
}
void DMA2_Stream4_IRQHandler(void)
{
	DMA2_Stream4_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF4;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF4;
	DMA2->HIFCR=DMA_HIFCR_CTEIF4;
	DMA2->HIFCR=DMA_HIFCR_CHTIF4;
	DMA2->HIFCR=DMA_HIFCR_CTCIF4;
}

void DMA2_Stream5_IRQHandler(void)
{
	DMA2_Stream5_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF5;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF5;
	DMA2->HIFCR=DMA_HIFCR_CTEIF5;
	DMA2->HIFCR=DMA_HIFCR_CHTIF5;
	DMA2->HIFCR=DMA_HIFCR_CTCIF5;
}

void DMA2_Stream6_IRQHandler(void)
{
	DMA2_Stream6_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF6;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF6;
	DMA2->HIFCR=DMA_HIFCR_CTEIF6;
	DMA2->HIFCR=DMA_HIFCR_CHTIF6;
	DMA2->HIFCR=DMA_HIFCR_CTCIF6;
}
void DMA2_Stream7_IRQHandler(void)
{
	DMA2_Stream7_handler();

	DMA2->HIFCR=DMA_HIFCR_CFEIF7;
	DMA2->HIFCR=DMA_HIFCR_CDMEIF7;
	DMA2->HIFCR=DMA_HIFCR_CTEIF7;
	DMA2->HIFCR=DMA_HIFCR_CHTIF7;
	DMA2->HIFCR=DMA_HIFCR_CTCIF7;
}

3. DMA Memory to Memory driver:

In main.c:

Include the dma_bsp header file:

#include "dma_bsp.h"

Also, include stdlib for random number generation:

#include "stdlib.h"

Declare a volatile variable to handle transfer complete interrupt:

volatile uint8_t finished=0;

Declare two arrays to hold the source and destination:

uint32_t dataSource[5]={0x00,0x22,0xFF,0x55,0x33};
uint32_t dataDest[5];

Declare DMA_ConfigTypedef data structure :

DMA_ConfigTypedef DMA_Config;

DMA2 Channel0 configuration:

__BSP_DMA2__CLOCK_ENABLE();

	DMA_Config.DMA_Channel=Channel0;
	DMA_Config.CircularMode=SingleTransfer;
	DMA_Config.MemorySize=word;
	DMA_Config.PerpheralSize=word;
	DMA_Config.MemoryIncMode=incMode;
	DMA_Config.PeripheralIncMode=incMode;
	DMA_Config.Direction=memory2Memory;
	DMA_Config.InterruptEnable=InterruptEnbaled;
	DMA_Config.TransferCompleteInterrupt=TransferComplet;
	DMA_Config.DMAStream=dma2stream0;

Configure the DMA:

BSP_DMA_Init(DMA2_Stream0, &DMA_Config);

In while loop:

		BSP_DMA_Transfer_Single_Buffer(DMA2_Stream0, &dataSource, &dataDest, 5);

		while(finished ==0){;}
		finished=0;
		for (int i=0; i<5;i++)
		{
			dataSource[i]=random()%256;
		}

In interrupt handler:

void DMA2_Stream0_handler(void)
{
	if((DMA2->LISR & DMA_LISR_TCIF0)==DMA_LISR_TCIF0)
	{
		finished=1;
	}

}

4. Code:

You may download the source code from here:

5. Results:

Using debug session, add both array to live expression and you should get the following:

We have successfully transfer 5 word data from one location to another.

Happy coding 🙂

2 Comments

  • H.S.Raghavendra Rao Posted August 20, 2023 2:08 am

    Dear Sir,
    Good Morning, It is a pleasure to go through your site,
    In this site, in 5th Item, Results, has some file not found Displayed,
    though the results are known, please kindly look at the problem.
    thanks with regards,
    HSR-Rao.

    • Husamuldeen Posted August 20, 2023 3:44 am

      Hi,
      thank you. The problem has been fixed.

Add Comment

Your email address will not be published. Required fields are marked *