🌱 Các kỹ thuật thiết kế luồng xử lý trong chương trình nhúng
Đối với một số chương trình nhỏ, các chương trình mà các bạn mới thực hành (blink LED, đọc nút bấm, ...) có một đặc điểm chung, đó là chương trình đều liên tục thực thi, kiểm tra một số lệnh nào đó, trong vòng lặp while (1). Điều này dẫn đến nhiều nhược điểm, chẳng hạn: Những lệnh đứng sau phải đợi những lệnh đứng trước thực thi xong, như vậy có thể gây bỏ lỡ các sự kiện nếu kích thước chương trình lớn.
➤ Việc bấm nút có thể không diễn ra thường xuyên, nhưng việc kiểm tra nó lại diễn ra liên tục ⇒ có thể gây lãng phí năng lượng. Vậy, đối với các chương trình nhúng, chúng ta cần có thêm 1 số phương pháp, kỹ thuật thiết kế khác ngoài cách thông thường này, nhằm giúp chương trình nhúng là tối ưu nhất về mặt thiết kế, tiết kiệm tài nguyên, và tránh các lỗi không đáng có.
Dưới đây mình sẽ giới thiệu với các bạn 3 cách thiết kế luồng xử lý đơn giản nhất trong chương trình nhúng, đó là Polling, Interrupt, DMA.
👉👉 Bài toán
Đọc dữ liệu từ cảm biến, dùng ADC, và hiển thị lên màn hình LCD.
👉👉 Polling
Cách mà chúng ta vẫn hay làm như vậy, trong vòng lặp while(1), gọi là kỹ thuật Polling - liên tục kiểm tra, liên tục thực thi. Mặc dù có một vài nhược điểm, nhưng polling cũng có những ưu điểm: Đơn giản, dễ hiểu, dễ thiết lập chương trình. Các hoạt động thực hiện rõ ràng, tuần tự, nên dễ Debug.
Tuy nhiên, với các chương trình lớn, phức tạp hơn, đòi hỏi đáp ứng nhanh hơn, thì polling sẽ rất khó đáp ứng được. Polling trong các trường hợp này có thể gây mất các sự kiện Chúng ta nên kết hợp thêm một số kỹ thuật thiết kế khác!
👉👉 Interrupt
Hiểu đơn giản thì tên của nó là interrupt ⇒ ngắt/gián đoạn, nó có thể là sự thay đổi logic ở 1 chân nào đó, hoặc là sự tràn của một cờ, truyền hết 1 byte dữ liệu, ... Nó sẽ làm gián đoạn hoạt động của vòng lặp while(1).
Chẳng hạn thay vì liên tục kiểm tra nút bấm, ta cài đặt cho nó là 1 ngắt. Thì khi bấm nút, chương trình sẽ bị gián đoạn, và CPU phải kiểm tra xem điều gì đang xảy ra !!! Như bài toán trên, chúng ta có thể bắt đầu ADC, sau đó làm công việc khác, chờ nó chuyển đổi xong, nhảy vào ngắt đọc giá trị đo được, rồi lại tiếp tục chương trình.
🧐🧐 Quá trình thực thi sau khi có yêu cầu ngắt:
Stacking → Chương trình con thực thi ngắt (ISR) → Unstacking
** Hiểu đơn giản Stacking là quá trình cất dữ liệu (trong các thanh ghi mà while(1) đang làm việc) vào một cái ngăn xếp - stack để khi trình thực thi nhảy sang ISR, rồi trở lại, các dữ liệu này sẽ được trả lại bởi quá trình unstacking 😃 Xem thêm về Interrupt tại đây!
🧐🧐 Ưu điểm là Interrupt là giúp chương trình đáp ứng nhanh với những cái ta cần. Có thể sử dụng chế độ tiết kiệm năng lượng khi vi điều khiển không làm gì.
Tuy nhiên, nhược điểm của nó là ta cần khống chế chương trình con thực thi ngắt ISR để tránh việc chương trình phục vụ một ngắt quá lâu. Lời khuyên là nên viết chương trình ISR càng ngắn về mặt thời gian càng tốt.
👉👉 DMA
DMA - Direct Memory Access, tức là truy cập trực tiếp bộ nhớ. Nghe "trực tiếp" là thấy nhanh rồi 😃 Kỹ thuật này để sử dụng để truyền dữ liệu trực tiếp giữa bộ nhớ và ngoại vi mà không thông qua CPU (trong lúc này, CPU có thể làm việc khác nhờ thế tiết kiệm thời gian CPU rất nhiều).
🧐🧐 Cần truyền kiểu như vậy thì ắt hẳn lượng dữ liệu phải khá lớn → Thường là thu dữ liệu từ các cảm biến về bộ nhớ hoặc là điều khiển trực tiếp các ma trận led mà không qua CPU 😃
🧐🧐 Ưu điểm của DMA là nó truyền dữ liệu nhanh hơn CPU, nhờ đó nâng cao hiệu suất của vi điều khiển & tiết kiệm năng lượng. Cái này cũng có nhược điểm là nếu dùng không hợp lý thì có khả năng nó sẽ tiêu thụ nhiều năng lượng hơn bình thường. Hơn nữa, phần cứng vi điều khiển cần phải hỗ trợ DMA nếu muốn sử dụng.
🙁🙁🙁 Các vi điều khiển 32-bit hầu như đều hỗ trợ DMA trên chip, trong khi những vi điều khiển 8-bit thì không. Nếu muốn sử dụng tính năng này với vi điều khiển 8-bit, cần kết nối phần cứng bên ngoài là bộ DMA Controller.
👉👉 Có thể kết hợp các kỹ thuật trên để có một chương trình tối ưu. Đây là các kỹ thuật xử lý với một luồng, sau này chúng ta có thể sẽ phải đối mặt với đa luồng, đa nhiệm RTOS !! Nên việc nắm vững các kỹ thuật trên, đặc biệt là Polling và Interrupt là rất quan trọng.