Bạn đang xem: dma là gì

 – DMA (Direct memory access): là một cơ chế truyền dữ liệu vận tốc cao từ ngoại vi tới bộ nhớ lưu trữ cũng như từ bộ nhớ lưu trữ tới bộ nhớ lưu trữ. Dữ liệu có thể được di chuyển một cách nhanh chóng mà không cần tới tác vụ từ CPU, tiết kiệm tài nguyên CPU cho các hoạt động khác.

Đang xem: Dma là gì

– Trong nhiều project mcu bạn cần đọc và ghi dữ liệu. Ví dụ bạn cần đọc dữ liệu từ ngoại vi như ADC và ghi các giá trị đọc được vào RAM. Hoặc trong trường hợp khác bạn cần gửi 1 khối dữ liệu sử dụng SPI. Khi đó bạn cần phải thực hiện đọc dữ liệu từ RAM và ghi nó vào thanh ghi SPI data. Bình thường nếu sử dụng cpu để làm việc này thì nó sẽ bị mất một khoảng thời gian đáng kể để xử lý. Trong những trường hợp này, để tránh việc cpu bận rộn và giành thời gian cho những thao tác khác thì ở những mcu thông dụng đều có trợ giúp DMA (direct memory access). Nó sẽ thực hiện việc giao tiếp với memory mà không cần dùng đến cpu.

* DMA của STM32 :

STM32 có 2 bộ DMA với 12 kênh (7 kênh DMA1 và 5 kênh DMA2), mỗi bộ quản lý việc truy cập bộ nhớ lưu trữ từ một hoặc nhiều ngoại vi. DMA cũng có tính năng phân xử độ ưu tiên giữa các DMA request.

– 12 kênh DMA độc lập, có thể thiết lập được. 7 kênh DMA1 và 5 kênh DMA2

– Software trigger được trợ giúp cho mỗi kênh, và được lập trình bởi software.

– Độ ưu tiên giữa các kênh DMA có thể lập trình bởi software (có 4 cấp ưu tiên là very high, high, medium, low) hoặc phần cứng.

– Phụ thuộc vào kích thước giữa nguồn và đích (byte, half word, word). Địac chỉ nguồn/đích phải phù phù hợp với kích thước dữ liệu.

– Trợ giúp truyền tải giữa:

+ Memory to memory

+ Peripheral to memory

+ Memory to peripheral

+ Peripheral to peripheral

– Có thể truy cập vào Flash, Sram, APB1, APB2 và AHB như nguồn và đích.

– Dữ liệu truyền nhận trợ giúp tới 65536

 

 

2. Tìm hiểu cách lập trình DMA trong STM32 thông qua ví dụ rõ ràng

Mỗi channel được điều khiển bởi 4 thanh ghi : Memory address, peripheral address, number of data and configuration. Và toàn bộ các channel đều có 2 thanh ghi được giành riêng là : DMA interrupt status register and interrupt flag clear register. Các channel của DMA có thể tạo ra 3 interupt là : transfer finished, half-finished and transfer error.

Xem Thêm  8 cách nghe nhạc Youtube khi tắt màn hình iPhone, Android mới nhất - nghe youtube khi tắt màn hình

Khởi đầu với 1 ví dụ là thực hiện công việc chuyển dữ liệu giữa 2 mảng. Trong số đó có 2 trường hợp là có sử dụng DMA và không sử dụng DMA mà để cpu thực hiện bình thường. Sau đó so sánh thời gian trong 2 trường hợp trên.

Trước khi đi vào phân tích code của ví dụ thì mình sẽ tìm hiểu biến cấu trúc của DMA đã được khái niệm sẵn bao gồm những thanh ghi tính năng như vậy nào :

Cấu trúc biến init DMA gồm 11 thành phần và ý ngh ĩa của từng thành phần như sau :– DMA_PeripheralBaseAddr , DMA_MemoryBaseAddr : Xác nhận địa chỉ của ngoại vi và địa chỉ của bộ nhớ lưu trữ cho DMA channel, hay nói cách khác là xác nhận địa chỉ nguồn và đích trong việc trao đổi dữ liệu. –DMA_DIR : Chọn hướng chuyển dữ liệu từ ngoại vi đến bộ nhớ lưu trữ hay từ bộ nhớ lưu trữ đến ngoại vi.

/**
defgroup DMA_data_transfer_direction **/ #define DMA_DIR_PeripheralDST ((uint32_t)0x00000010) #define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000)

DMA_BufferSize : Kích thước của mảng dữ liệu.

DMA_PeripheralInc, DMA_MemoryInc :

+ DMA_PeripheralInc : So với ngoại vi chúng ta nên disable mode này do nếu bạn bật mode này thì mỗi lần chuyển dữ liệu thì địa chỉ ngoại vi sẽ tăng dần, điều này là không thiết yếu và rất nguy hiểm nếu nh ư bạn không nắm vững địa chỉ trỏ đến tiếp theo. + DMA_MemoryInc : So với memory bạn cần enable mode này, mỗi khi chuy ển đổi xảy ra bạn cần tăng địa chỉ bộ nhớ lưu trữ của bạn bởi ví dụ biến ADCValue có đến 3 phần tử, nếu không tăng địa chỉ lên thì chỉ duy nhất có biến ADCValuevàlt;0vàgt; là có dữ liệu.– DMA_PeripheralDataSize , DMA_MemoryDataSize : Chọn kích thước mảng dữ liệu ADCValue gồm : Byte, Haftword và Word.

/**
defgroup DMA_peripheral_data_size */ #define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) #define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) #define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200)– DMA_Mode : Circular mode & NonCircular mode

+ Chọn mode DMA chính sách vòng tròn, có nghĩa là việc chuyển hóa liên tục lặp lại. Khi circular mode được actived thì số dữ liệu được transfer sẽ tự động reload lại với những thiết lập đã được lập trình theo những thông số kỹ thuật config cho channel. + Nếu channel được config ở chính sách concircular mode thì sẽ không có DMA request được tạo sau mỗi lần transfer. /**
defgroup DMA_circular_normal_mode */ #define DMA_Mode_Circular ((uint32_t)0x00000020) #define DMA_Mode_Normal ((uint32_t)0x00000000)– DMA_Priority : Xác nhận độ ưu tiên của kênh DMA ,có 4 độ ưu tiên bao gồm :

Xem Thêm  UniKey 4.3 RC5 - cài đặt phần mềm proshow producer

+ DMA_Priority_High + DMA_Priority_Low + DMA_Priority_Medium + DMA_Priority_VeryHigh

DMA_M2M : Kênh DMA cũng có thể được kích hoạt mà không cần request từ ngoại vi, chính sách này được gọi là memory to memory mode. Nếu bit MEM2MEM trong thanh ghi DMA_CCRx được set thì channel sẽ init transfer ngay sau khoảng thời gian được enable bằng software nghĩa là enable bit EN trong thanh ghi DMA_CCRx. Quá trình transfer sẽ ngừng mỗi khi thanh ghi DMA_CNDTRx zero. Memory to memory mode không được sử dụng đồng thời với Circular mode./**
defgroup DMA_memory_to_memory **/#define DMA_M2M_Enable ((uint32_t)0x00004000)#define DMA_M2M_Disable ((uint32_t)0x00000000)Đây là code DMA chuyển dữ liệu trong trường hợp từ memory đến memory :

#include “stm32f10x.h”#include “leds.h”#define ARRAYSIZE 800volatile uint32_t status = 0;volatile uint32_t ι;int main(void){//initialize source and destination arraysuint32_t source;uint32_t destination;//initialize arrayfor (ι=0; ι
Khởi đầu phân tích :

Trước nhất tất cả chúng ta tạo ra 2 mảng dữ liệu là : source và destination. Kích thước của mảng được xác nhận bởi ARRAYSIZE, trong ví dụ này kích thước là 800.Trong ví dụ này,ta sử dụng trạng thái của Led để báo hiệu quá trình transfer dữ liệu start và stop trong cả 2 mode : DMA và CPU. 

+ Trước nhất ta phải cấu hình enable clock cho DMA1 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE).

Xem thêm: Trùng Sinh Là Gì – Giải Nghĩa Một Số Thể Loại Truyện

+ Sau đó khởi đầu cấu hình thông qua cấu trúc DMA_InitStructure như đã phân tích bên trên. Trong ví dụ này ta chọn DMA1 channel1, gọi hàm DMA_DeInit(DMA1_Channel1) để chắc nịch rằng DMA được reset về giá trị mặc định ban đầu.

+ Sau đó chọn DMA mode memory to memory(DMA_InitStructure.DMA_M2M = DMA_M2M_Enable)

+ Chọn normal DMA mode hay thường hay gọi là nonCircular mode(DMA_InitStructure.DMA_Mode = DMA_Mode_Normal).

+ Chọn chính sách ưu tiên cho kênh DMA này laafe Medium (DMA_InitStructure.DMA_Priority = DMA_Priority_Medium).

+ Chọn kích thước mảng dữ liệu để transfer là 32-bit world (DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word). Tương tự với cả peripheral và memory address.

Note : Nếu kích thước dữ liệu của 2 thành phần trên không giống nhau,ví dụ 32-bit source và 8-bit destination thì DMA sẽ thực hiện thành 4 chu kỳ với mỗi chu kỳ là 8 bit.

+ Sau khoảng thời gian đã cấu hình địa chỉ source và destination, cũng như kích thước dữ liệu để gửi. Ta sử dụng hàm

DMA_Init(DMA_Channel1, &DMA_InitStructure) để init các thông số kỹ thuật cấu hình bên trên vào thanh ghi.

Xem Thêm  File XPS là gì? Cách mở và chuyển đổi file XPS sang PDF, Word đơn giản - chuyển đổi file xml sang excel

+ Hiện thời thì DMA có thể sẵn sàng để transfer dữ liệu, bất kì khi nào lệnh sau được thực thi DMA_Cmd(DMA_Channel1, ENABLE).

+  Để bắt interrupt khi quá trình DMA transfer complete trên channel1. Ta cấu hình interrupt như sau :

NVIC_InitTypeDef NVIC_InitStructure;

//Enable DMA1 channel IRQ Channel */

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

 Trước khi khởi đầu chuyển hóa bằng DMA thì ta bật led on để báo trạng thái khởi đầu LEDToggle(LEDG) . Khi quá trình chuyển hóa vừa xong thì nó sẽ tạo ra 1 interrupt complete và thực hiển đảo trạng thái led trong interrupt này để báo hiệu.

voidDMA1_Channel1_IRQHandler(void){

//Test on DMA1 Channel1 Transfer Complete interrupt

if(DMA_GetITStatus(DMA1_IT_TC1))

{

status=1;

LEDToggle(LEDG);

//Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits

DMA_ClearITPendingBit(DMA1_IT_GL1);

}

}

+ Như vậy này là code cho phần chuyển dữ liệu bằng DMA ,tiếp theo là phần chuyển dữ liệu bằng CPU bình thường và ta cũng sử dụng trạng thái của LED để xem xét thời gian chuyển hóa.

Xem thêm: Caffeine Là Gì – Caffeine Tốt Hay Xấu Cho Sức Khỏe

//wait for DMA transfer to be finished

while(status==0) {};

LEDToggle(LEDB);

for (ι=0; ι

{

destination

}

LEDToggle(LEDB);

– Trong ví dụ này, LEDG (DMA) được kết nối đến GPIOC pin 9 và LEDB (CPU) được kết nối đến GPIOC pin 8, Để xem xét rõ hơn quá trình transfer ta kết nối 2 pin này với OSC như sau :

*

– Transfer sử dụng DMA mất 214μs:

*

– Trong lúc sử dụng CPU để sao chép memory memory mất 544μs (gần gấp 3 lần so với sử dụng DMA):

*

– Ví dụ này cho thấy vận tốc truyền dữ liệu nhanh hơn đáng kể so với việc sử dụng CPU bình thường và lợi nhuận lớn nhất là CPU hoàn toàn rảnh rổi trong lúc transfer và có thể làm nhiệm vụ khác hoặc chỉ đơn giản là vào chính sách sleep mode.

– Kỳ vọng ví dụ này giúp bạn có một ý tưởng về tầm trọng yếu DMA . Với DMA tất cả chúng ta có thể làm vô số công việc ở mức harward . 


Xem thêm những thông tin liên quan đến đề tài dma là gì

STM32F103C8T6 – Giao tiếp SPI – Thư viện Standard – phần 2 – sử dụng DMA

alt

  • Tác giả: Lập trình Vi điều khiển
  • Ngày đăng: 2020-03-29
  • Nhận xét: 4 ⭐ ( 8355 lượt nhận xét )
  • Khớp với kết quả tìm kiếm: http://vidieukhien.org/stm32f103c8t6-giao-tiep-spi-phan-2-su-dung-dma.html
    Tham khảo thêm về DMA
    http://vidieukhien.org/stm32f4-discovery-timer-4-pwm-dma-keil-c-v5-thanh-ghi.html

Xem thêm các nội dung khác thuộc thể loại: Thủ thuật máy tính

By ads_php