Skip to content

19 Giới thiệu nguyên lý DMA (Direct Memory Access)

Kiến thức cơ bản về DMA

Các phương pháp truyền dữ liệu

Khi cần truyền dữ liệu giữa bộ nhớ và ngoại vi, có ba phương pháp phổ biến:

  1. Phương pháp thăm dò (Polling) Trong vòng lặp chính, CPU liên tục kiểm tra các cờ trạng thái của ngoại vi để xác định có cần truyền dữ liệu hay không. Nếu có, CPU sẽ tự mình di chuyển dữ liệu giữa bộ nhớ và ngoại vi. → Khi việc truyền dữ liệu diễn ra thường xuyên hoặc dữ liệu lớn, cách này sẽ làm giảm hiệu năng và khả năng phản hồi của hệ thống.
  2. Phương pháp ngắt (Interrupt) Khi ngoại vi cần truyền dữ liệu, nó sẽ tạo ra một ngắt, khiến CPU tạm ngưng công việc hiện tại để xử lý dữ liệu trong hàm ngắt. → CPU không cần liên tục kiểm tra cờ trạng thái. Tuy nhiên, CPU vẫn phải xử lý việc sao chép dữ liệu, nên nếu ngắt xảy ra liên tục, việc chuyển đổi ngữ cảnh sẽ tốn tài nguyên và làm chậm hệ thống.
  3. DMA (Direct Memory Access) DMA là một phần cứng độc lập trong vi điều khiển, cung cấp kênh truyền dữ liệu riêng giữa bộ nhớ và ngoại vi, mà không cần CPU tham gia. → Đây là phương pháp truyền dữ liệu hiệu quả nhất, giúp CPU rảnh tay để xử lý các tác vụ khác.

Tổng kết:

DMA là giải pháp tối ưu cho các bài toán truyền dữ liệu lớn hoặc thường xuyên trong hệ thống nhúng.

DMA là gì?

DMA (Direct Memory Access – Truy cập bộ nhớ trực tiếp) là một cơ chế phần cứng cho phép truyền dữ liệu giữa ngoại vi và bộ nhớ, hoặc giữa hai vùng bộ nhớkhông cần CPU can thiệp.

→ Điều này giúp tránh việc CPU phải liên tục xử lý ngắt và sao chép dữ liệu, đặc biệt khi khối lượng dữ liệu lớn, từ đó nâng cao hiệu suất tổng thể của hệ thống.

DMA là một bộ điều khiển phần cứng tích hợp (DMA Controller), cho phép tự động di chuyển khối dữ liệu từ địa chỉ nguồn đến địa chỉ đích mà CPU chỉ cần cấu hình ban đầu.

DMA hỗ trợ:

  • Nhiều độ rộng dữ liệu (byte, half-word, word…)
  • Chế độ truyền burst (truyền theo cụm)
  • Thuật toán sinh địa chỉ tự động
  • Cấu hình ưu tiên và nhiều chế độ truyền khác nhau

Tất cả giúp DMA linh hoạt và mạnh mẽ, phù hợp với nhiều tình huống trong ứng dụng nhúng.

Giới thiệu DMA trong STM32

Vi điều khiển STM32F407VET6 tích hợp hai bộ điều khiển DMA: DMA1DMA2.

  • Mỗi bộ điều khiển DMA có:
    • 2 giao diện bus AHB
    • 8 kênh truyền
    • Mỗi kênh đều có FIFO 4 từ (word) sâu, giúp tăng hiệu suất truyền dữ liệu.

→ Như vậy, toàn bộ hệ thống có tổng cộng 16 kênh DMA.

  • Mỗi kênh DMA có thể được gán cho một hoặc nhiều ngoại vi cụ thể để thực hiện truyền dữ liệu tự động.
  • STM32 sử dụng bộ điều phối ưu tiên (arbiter) bên trong để xử lý xung đột DMA và ưu tiên truy cập bus.
  • DMA hỗ trợ truyền dữ liệu có độ rộng 8 bit, 16 bit hoặc 32 bit, phù hợp với nhiều loại ngoại vi và dữ liệu.

Các tính năng chi tiết về DMA có thể tham khảo tại trang 302 của tài liệu Reference Manual, như hình minh họa dưới đây.

img

Các chế độ truyền DMA

Bộ điều khiển DMA trong vi điều khiển STM32F407VET6 có hai giao diện bus AHB, lần lượt dùng để truy cập bộ nhớ (Memory)ngoại vi (Peripheral).

DMA hỗ trợ ba chế độ truyền dữ liệu, bao gồm:

  1. Ngoại vi → Bộ nhớ
    • DMA đọc dữ liệu từ ngoại vi qua giao diện AHB-peripheral, sau đó ghi vào bộ nhớ qua giao diện AHB-memory.
    • Ví dụ: DMA nhận dữ liệu từ USART là kiểu truyền từ ngoại vi đến bộ nhớ.
  2. Bộ nhớ → Ngoại vi
    • DMA đọc dữ liệu từ bộ nhớ, sau đó ghi dữ liệu ra ngoại vi.
    • Ví dụ: DMA truyền dữ liệu qua USART là kiểu truyền từ bộ nhớ đến ngoại vi.
  3. Bộ nhớ → Bộ nhớ
    • DMA đọc dữ liệu từ vùng bộ nhớ nguồn, và ghi sang vùng bộ nhớ đích thông qua hai giao diện bus AHB khác nhau.
    • Phù hợp với các ứng dụng sao chép khối dữ liệu lớn trong RAM mà không cần CPU can thiệp.

Trong các kiểu truyền này, cả bộ nhớ và ngoại vi đều có thể được cấu hình là nguồn hoặc đích, tùy thuộc vào nhu cầu truyền dữ liệu.

Sơ đồ minh họa quá trình truyền dữ liệu từ bộ nhớ được thể hiện như sau

img

外设端数据传输如图所示。

img

Bảng ánh xạ yêu cầu ngoại vi của DMA

Mỗi bộ điều khiển DMA (DMA1 và DMA2) trong STM32F407VET6 có 8 kênh (Stream). Mỗi kênh này có thể được gán cho nhiều yêu cầu truyền dữ liệu từ các ngoại vi khác nhau.

Bảng ánh xạ giữa ngoại vi và các kênh DMA được quy định rõ ràng trong tài liệu Reference Manual. Các ngoại vi như USART, SPI, ADC, TIM... sẽ gửi yêu cầu DMA đến các kênh tương ứng tùy thuộc vào cấu hình dòng chip và sơ đồ kết nối bên trong.

DMA1DMA2 có bảng ánh xạ khác nhau – bạn có thể tham khảo sơ đồ ánh xạ chi tiết trong tài liệu (thường ở các trang quanh mục DMA – ví dụ: bảng 36, bảng 37...)

img

img

img

Cơ chế phân quyền truy cập (Arbitration)

Mỗi bộ điều khiển DMA trong STM32 có hai bộ phân quyền (arbiter) – một cho ngoại vi, một cho bộ nhớ.

Khi nhiều yêu cầu DMA xảy ra cùng lúc, arbiter sẽ quyết định yêu cầu nào được xử lý trước, dựa trên mức độ ưu tiên của từng kênh DMA.

Quy tắc phân quyền:

  • Ưu tiên phần mềm (Software priority): Gồm 4 mức độ:

    • Thấp (Low)
    • Trung bình (Medium)
    • Cao (High)
    • Rất cao (Very High)

    → Có thể cấu hình bằng trường PRIO trong thanh ghi DMA_CHxCTL (hoặc tương đương tùy vào dòng chip).

  • Ưu tiên phần cứng (Hardware priority): Nếu nhiều kênh có cùng mức ưu tiên phần mềm, thì kênh có số thứ tự nhỏ hơn sẽ được ưu tiên hơn. → Ví dụ: nếu DMA_Stream0 và DMA_Stream3 cùng mức ưu tiên, thì Stream0 sẽ được xử lý trước.

FIFO (Fist in first out)

Mỗi kênh DMA trong STM32 đều được trang bị một FIFO sâu 4 từ (word), dùng để đệm dữ liệu tạm thời trong quá trình truyền.

  • Khi DMA đọc dữ liệu từ địa chỉ nguồn, dữ liệu sẽ được lưu tạm vào FIFO
  • Sau đó, dữ liệu từ FIFO sẽ được truyền đến địa chỉ đích

Tùy theo cấu hình, DMA hỗ trợ hai chế độ xử lý dữ liệu:

  1. Chế độ truyền đơn (Single transfer mode)
    • Mỗi lần chỉ xử lý một phần tử dữ liệu (byte/half-word/word)
  2. Chế độ truyền theo khối (Burst transfer mode)
    • Truyền nhiều phần tử dữ liệu trong một lần xử lý → hiệu quả cao hơn

Lưu ý: Khi DMA hoạt động ở chế độ bộ nhớ đến bộ nhớ (Memory-to-Memory), chỉ hỗ trợ chế độ truyền theo khối (burst mode).

Thuật toán sinh địa chỉ (Address Generation)

DMA hỗ trợ hai thuật toán sinh địa chỉ độc lập cho cả ngoại vibộ nhớ:

  • Chế độ địa chỉ cố định (Fixed mode) Địa chỉ truyền luôn giữ nguyên là địa chỉ cơ sở (base address) đã cấu hình ban đầu.
  • Chế độ địa chỉ tăng dần (Increment mode) Mỗi lần truyền, DMA sẽ tự động tăng địa chỉ lên một giá trị tương ứng với độ rộng dữ liệu:
    • Tăng 1 nếu truyền 8-bit
    • Tăng 2 nếu truyền 16-bit
    • Tăng 4 nếu truyền 32-bit

Ứng dụng:

  • Địa chỉ ngoại viđịa chỉ của thanh ghi ngoại vi, ví dụ như thanh ghi nhận dữ liệu USARTx->DR → Địa chỉ này luôn cố định, vì DMA luôn ghi/đọc tại cùng một thanh ghi → nên dùng chế độ địa chỉ cố định
  • Địa chỉ bộ nhớcon trỏ đến mảng đệm trong RAM → Vì DMA cần ghi vào các phần tử liên tiếp trong mảng → nên dùng chế độ địa chỉ tăng dần

Chế độ lặp (Circular Mode)

Chế độ lặp (circular mode) được sử dụng để xử lý các yêu cầu DMA liên tục từ ngoại vi, chẳng hạn như truyền dữ liệu liên tục từ USART hoặc ADC.

  • Trong chế độ này, sau mỗi lần DMA hoàn thành truyền:
    • CNT (số lượng dữ liệu cần truyền) sẽ tự động được nạp lại
    • Cờ truyền hoàn tất (TC) sẽ được đặt lên 1
  • DMA sẽ tiếp tục truyền dữ liệu trong các chu kỳ tiếp theo mà không cần CPU can thiệp, cho đến khi:
    • Gặp lỗi truyền, hoặc
    • DMA channel bị tắt (disable)

So sánh giữa hai chế độ truyền:

1. Chế độ truyền đơn (Normal mode):

Khi DMA truyền xong dữ liệu:

  • Sẽ kích hoạt ngắt DMA

  • Trong trình xử lý ngắt:

    • Cần tắt kênh DMA

    • Cập nhật lại số lượng dữ liệu cần truyền (NDTR)

    • Bật lại kênh DMA

      → Lưu ý: chỉ khi DMA channel đang tắt, mới có thể cập nhật số lượng dữ liệu truyền được.

2. Chế độ lặp (Circular mode):

Khi DMA truyền xong:

  • Phần cứng tự động nạp lại NDTR
  • DMA tự động tiếp tục vòng truyền tiếp theo
  • Không cần xử lý ngắt hay can thiệp phần mềm

Ngắt trong DMA (Interrupts)

Mỗi kênh DMA trong STM32 đều có bộ ngắt riêng, liên quan đến 5 loại sự kiện ngắt, bao gồm:

  1. Ngắt khi truyền hoàn tất (Transfer Complete – TC)
  2. Ngắt khi truyền được một nửa (Half Transfer – HT)
  3. Ngắt lỗi truyền (Transfer Error – TE)
  4. Ngắt do bất thường trong chế độ truyền đơn (Direct Mode Error)
  5. Ngắt do lỗi FIFO (FIFO Error)

Bất kỳ sự kiện nào trong số này xảy ra đều có thể kích hoạt ngắt DMA.

Nhóm các loại sự kiện ngắt:

Các sự kiện trên có thể chia thành 3 loại chính:

  • Dạng cờ (Flags):
    • Truyền hoàn tất (TC)
    • Truyền nửa chừng (HT)
  • Dạng bất thường (Abnormal):
    • Bất thường ở chế độ truyền đơn
    • Bất thường ở FIFO
  • Dạng lỗi (Errors):
    • Lỗi truyền
    • Lỗi FIFO

Phản ứng của DMA với từng loại ngắt:

  • Nếu là bất thường (abnormal events): → DMA vẫn tiếp tục truyền, không bị dừng
  • Nếu là lỗi (error events): → DMA sẽ dừng ngay lập tức

Nguyên lý thí nghiệm

DMA hỗ trợ truyền dữ liệu cho nhiều loại ngoại vi. Trong phần này, ta sẽ lấy ví dụ về việc nhận dữ liệu UART bằng DMA để minh họa.

Thông thường, có 3 phương pháp nhận dữ liệu UART:

  • Dùng thăm dò (polling): CPU liên tục kiểm tra xem có dữ liệu đến không
  • Dùng ngắt (interrupt): Khi có dữ liệu đến, UART sinh ngắt để xử lý
  • Dùng DMA: Tự động di chuyển dữ liệu từ UART vào bộ nhớ

Trên thực tế, phương pháp dùng ngắt khá phổ biến, và hoạt động hiệu quả với dữ liệu nhỏ lẻ. Tuy nhiên, với dữ liệu lớn hoặc truyền nhiều, phương pháp ngắt sẽ trở nên kém hiệu quả, do CPU phải xử lý nhiều ngắt. Vì vậy, DMA là giải pháp lý tưởng khi cần truyền nhận dữ liệu lớn và liên tục.

Tư duy sử dụng DMA để nhận dữ liệu UART

  • Khi UART phát hiện có dữ liệu đến, DMA sẽ tự động ghi dữ liệu vào bộ đệm RAM đã được cấu hình trước.
  • Trong lúc đó, CPU vẫn xử lý các tác vụ khác, không bị ảnh hưởng.
  • Sau khi một khung dữ liệu hoàn tất, UART sẽ phát sinh ngắt "idle" (ngắt phát hiện đường truyền rảnh) để báo cho chương trình biết rằng một frame đã nhận xong.
  • Lúc này, CPU mới can thiệp để xử lý dữ liệu đã được DMA truyền xong.

Ưu điểm:

  • Trong toàn bộ quá trình nhận dữ liệu, chỉ xảy ra đúng 1 lần ngắt
  • Không chiếm CPU trong suốt quá trình truyền dữ liệu
  • Hiệu quả cao và phù hợp cho truyền dữ liệu theo khối lớn