Building Board Support Package (BSP) for STM32F411-Nucleo64 Part13.1: DMA Driver

In this thirteenth part, section 1 of board support package, we shall develop the header for DMA in order to configure it later with different modes.

In this guide, we shall cover the following:

  • Developing the header file.

1. Developing the header file:

We start off by creating new header file with name of dma_bsp.h

Within the header guard, include the following:

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

We need STM32F4xx header to access the registers.

Also, stdint to handle variable type.

We shall define two macros to enable clock access to either DMA1 or DMA2:

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

Since STM32F411 has two DMAs and each DMA has 7 streams, we shall define them as following:

typedef enum
{
	dma1stream0=0,
	dma1stream1,
	dma1stream2,
	dma1stream3,
	dma1stream4,
	dma1stream5,
	dma1stream6,
	dma1stream7,
	
	dma2stream0,
	dma2stream1,
	dma2stream2,
	dma2stream3,
	dma2stream4,
	dma2stream5,
	dma2stream6,
	dma2stream7,

};

This will be handy when enabling the interrupt in NVIC.

With each DMA Stream, you can use one of the 8 channels, we can define these channels as following:

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

Within DMA, you can control both, the memory and peripheral burst mode as following:

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

You can either use single or double buffer mode for data management:

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

Also, the priority of the stream as following:

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

}DMA_StreamPriorityTypedef;

Also, control the peripheral increment offset:

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

Memory and peripheral size as following:

typedef enum
{
	byte=0,
	halfWord,
	word

}DMA_SizeTypedef;

Use fixed or increment mode:

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

Use circular mode or not:

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

Direction of the DMA:

typedef enum
{
	peripheral2Memory=0,
	memory2Peripheral,
	memory2Memory

}DMA_DirectionTypedef;

To choose either the DMA or the peripheral is the controller:

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

For the interrupt functionality:

typedef enum
{
	InterruptDisabled=0,
	InterruptEnbaled=1,

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

Data structure to handle DMA configuration:

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;

In next section, we shall develop DMA driver to move data from one memory location to another using memory to memory mode.

Stay tuned.

Add Comment

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