DMA - Direct Memory Access

Introduction to DMA

DMA (Direct Memory Access)—direct memory access, is a peripheral of the microcontroller. Its main function is to move data, but it does not need to occupy the CPU, that is, when transferring data, the CPU can do other things, as if It's the same as multithreading. Data transfer supports from peripheral to memory or memory to memory, where the memory can be SRAM or FLASH. The DMA controller includes DMA1 and DMA2, of which DMA1 has 7 channels and DMA2 has 5 channels. The channels here can be understood as a kind of pipeline for transmitting data. It should be noted that DMA2 only exists in large-capacity microcontrollers.

DMA Functional Block Diagram

The DMA controller is independent of the core and belongs to a separate peripheral with a relatively simple structure. From the perspective of programming, we only need to master the three parts of the functional block diagram. See Figure 22-1: DMA Controller block diagram.

1

1. ①DMA request

If the peripheral wants to transmit data through DMA, it must first send a DMA request to the DMA controller. After the DMA receives the request signal, the controller will give the peripheral a response signal. When the peripheral responds and the DMA controller receives the response After the signal, the DMA transfer will be started until the transfer is completed. DMA has two controllers, DMA1 and DMA2. DMA1 has 7 channels and DMA2 has 5 channels. The channels of different DMA controllers correspond to different peripheral requests, which determines how we should set the software programming. See the DMA request mapping table.

2

3


2. ① Channel

DMA has 12 independent programmable channels, of which DMA1 has 7 channels, DMA2 has 5 channels, each channel corresponds to the DMA request of different peripherals. Although each channel can receive requests from multiple peripherals, only one can be received at the same time, not multiple at the same time.

3. ② Arbiter

When multiple DMA channel requests occur, it means that there is an order of response and processing, which is also managed by the arbiter. The arbiter manages DMA channel requests in two phases. The first stage is a software stage, which can be set in the DMA_CCRx register and has 4 levels: very high, high, medium and low priorities. The second stage belongs to the hardware stage. If two or more DMA channel requests have the same priority, their priority depends on the channel number. The lower the number, the higher the priority. For example, channel 0 is higher than channel 1. In bulk and interconnect products, the DMA1 controller has priority over the DMA2 controller.

DMA data configuration

Using DMA, the core is to configure the data to be transmitted, including where the data comes from, where it is going, what is the unit of the transmitted data, how much data is to be transmitted, whether it is a one-time transfer or a cyclic transfer, and so on.

1. Where to go from where

      We know that DMA transfers data in three directions: from peripheral to memory, from memory to peripheral, and from memory to memory. The specific direction DMA_CCR bit 4 DIR configuration: 0 means from peripheral to memory, 1 means from memory to peripheral. The peripheral addresses involved here are configured by DMA_CPAR, and the memory address is configured by DMA_CMAR.

peripheral to memory

     Take ADC acquisition as an example when we use transfer from peripheral to memory. The address of the DMA peripheral register corresponds to the address of the ADC data register, and the address of the DMA memory is the address of our custom variable (used to receive and store the data collected by AD). In the direction we set the peripheral as the source address.

memory to peripheral

     When we use the transmission from memory to peripherals, take the serial port to send data to the computer as an example. The address of the DMA peripheral register corresponds to the address of the serial port data register, and the address of the DMA memory is the address of our custom variable (equivalent to a buffer used to store the data sent to the computer through the serial port). In the direction we set the peripheral as the destination address.

memory to memory

     When we use the transfer from memory to memory, take the example of copying data from internal FLASH to internal SRAM. The address of the DMA peripheral register corresponds to the address of the internal FLASH (we treat the internal FALSH as a peripheral here), and the address of the DMA memory is our custom variable (equivalent to a buffer, used to store data from the internal FLASH data) address. In the direction we set the peripheral (ie the internal FLASH) as the source address. The difference from the above two is that the DMA_CCR bit 14: MEM2MEM: memory-to-memory mode needs to be configured to 1 here to start M2M mode.

2. How much to pass and what is the unit?

      After we configure where the data is going to come from, we also need to know how much data we want to transmit and what the unit of the data is.

      Taking the serial port sending data to the computer as an example, we can send a lot of data to the computer at one time, the specific amount is configured by DMA_CNDTR, which is a 32-bit register, and can only transmit 65535 data at most at a time.

      In order for the data to be transmitted correctly, the data width stored in the source and destination addresses must be the same. The serial port data register is 8 bits, so the data we define to be sent must also be 8 bits. The data width of peripheral is configured by PSIZE[1:0] of DMA_CCRx, which can be 8/16/32 bits, and the data width of memory is configured by MSIZE[1:0] of DMA_CCRx, which can be 8/16/32 bits.

     Under the control of the DMA controller, in order to move data from one place to another in an orderly manner, the increment mode of the data pointers on both sides must be set correctly. The address pointer of peripheral is configured by PINC of DMA_CCRx, and the address pointer of memory is configured by MINC. Taking the serial port to send data to the computer as an example, there is a lot of data to be sent. After each one is sent, the address pointer of the memory should be incremented by 1, and there is only one serial port data register, so the address pointer of the peripheral device is fixed. The increment mode of the specific data pointer is determined by the actual situation.

3. When will the transfer complete

      When the data transmission is completed, we can identify it by querying the flag bit or by interrupting. Each DMA channel will have a corresponding flag bit when the DMA transfer is halfway through, the transfer is completed and the transfer error occurs. If this type of interrupt is enabled, an interrupt will be generated. For the detailed description of each flag bit, please refer to the detailed description of the DMA interrupt status register DMA_ISR.

      The transmission is also divided into two modes, one-time transfer or cyclic transfer. One-time transfer is well understood, that is, it stops after one transfer. If you want to transfer again, you must turn off the DMA enable and then reconfigure to continue the transfer. Cyclic transmission refers to the cyclic transmission of the configuration when the first transmission is restored after a transmission is completed, and it is repeated continuously. Specifically controlled by the CIRC cycle mode bits in the DMA_CCRx register.

DMA initialization structure details

     The standard library function establishes an initialization structure xxx_InitTypeDef for each peripheral (xxx is the name of the peripheral). The structure members are used to set the peripheral working parameters, and the standard library function xxx_Init() calls these setting parameters to enter the setting The corresponding registers of the peripherals are used to configure the working environment of the peripherals. The combination of the structure xxx_InitTypeDef and the library function xxx_Init is the essence of the standard library. After understanding the meaning of each member of the structure xxx_InitTypeDef, the peripheral can be used freely. The structure xxx_InitTypeDef is defined in the stm32f10x_xxx.h (the following xxx is the peripheral name) file, and the library function xxx_Init is defined in the stm32f10x_xxx.c file. We can combine the comments in these two files when programming.

DMA_ InitTypeDef initialization structure

typedef struct
 {
 uint32_t DMA_PeripheralBaseAddr; // Peripheral address 
 uint32_t DMA_MemoryBaseAddr; // Memory address 
 uint32_t DMA_DIR; // Transfer direction 
 uint32_t DMA_BufferSize; // Transfer number 
 uint32_t DMA_PeripheralInc; // Peripheral address increment mode 
 uint32_t DMA_MemoryInc; // Memory address increment mode 
 uint32_t DMA_PeripheralDataSize; // Peripheral data width 
 uint32_t DMA_MemoryDataSize; // Memory data width 
 uint32_t DMA_Mode; // Mode selection 
 uint32_t DMA_Priority; // Channel priority 
 uint32_t DMA_M2M; // Memory to memory mode 
 } DMA_InitTypeDef;
1) DMA_PeripheralBaseAddr: Peripheral address, set the value of the DMA_CPAR register; generally set to the data register address of the peripheral, if it is a memory-to-memory mode, set it to one of the memory addresses. 2) DMA_Memory0BaseAddr: memory address, set the DMA_CMAR register value; generally set to the first address of our custom memory area

3) DMA_DIR: transfer direction selection, optional peripheral to memory, memory to peripheral. It sets the value of the DIR[1:0] bits of the DMA_CCR register. There is no memory-to-memory direction selection here. When using memory-to-memory, you only need to use one of the memories as a peripheral.

4) DMA_BufferSize: Set the number of data to be transferred, and initialize the value of the DMA_CNDTR register.

5) DMA_PeripheralInc: If configured as DMA_PeripheralInc_Enable, the peripheral address auto-increment function is enabled, which sets the value of the PINC bit of the DMA_CCR register; generally, peripherals have only one data register, so this bit is generally not enabled.

6) DMA_MemoryInc: If it is configured as DMA_MemoryInc_Enable, the memory address auto-increment function is enabled, which sets the value of the MINC bit of the DMA_CCR register; our custom memory area generally stores multiple data, so it is necessary to enable the memory address auto-increment function. Incremental function.

7) DMA_PeripheralDataSize: Peripheral data width, optional byte (8 bits), half word (16 bits) and word (32 bits), it sets the value of the PSIZE[1:0] bits of the DMA_CCR register.

8) DMA_MemoryDataSize: Memory data width, optional byte (8 bits), half word (16 bits) and word (32 bits), it sets the value of the MSIZE[1:0] bits of the DMA_CCR register. When transferring data between peripherals and memory, the data width on both sides should be set to the same size.

9) DMA_Mode: DMA transfer mode selection, optional one-time transfer or cyclic transfer, it sets the value of the CIRC bit in the DMA_CCR register. Routine Our ADC acquisition is continuous loop, so use loop transfer mode.

10) DMA_Priority: The priority of the channel is set by software, there are 4 optional priority levels, which are very high, high, medium and low respectively. It sets the value of the PL[1:0] bits of the DMA_CCR register. The DMA channel priority is only meaningful when multiple DMA channels are used at the same time. If it is a single channel, the priority can be set arbitrarily.

11) DMA_M2M: memory-to-memory mode, used when using memory-to-memory, set bit 14 MEN2MEN of DMA_CCR to enable memory-to-memory mode.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325127598&siteId=291194637