Title Image

Blog Logo

🌱 Volatile Keyword

 🌱 Volatile keyword

    Trong lập trình C nhúng mình hay gặp khai báo biến với từ khóa volatile. Việc khai báo biến volatile rất cần thiết để tránh những lỗi sai khó phát hiện do tính năng optimization của compiler.

    Có 3 trường hợp thường được sử dụng của từ khóa Volatile trong các ứng dụng nhúng:

    👉 Thanh ghi ngoại vi có ánh xạ đến ô nhớ

    Các thiết bị ngoại vi (GPIO, UART, ...) chứa các thanh ghi mà giá trị của nó có thể thay đổi ngoài ý muốn của dòng chương trình, đặc biệt là những thanh ghi trạng thái.

    Ví dụ: đợi một nút bấm, với địa chỉ thanh ghi GPIO tương ứng nút bấm được định nghĩa như hình 1.

  • Ở đây nếu không có Volatile, con trỏ button sẽ đọc giá trị tại địa chỉ 0x40020810 (và giá trị này mắc định đang là 0).
  • Khi đó compiler sẽ tối ưu - optimize điều kiện trong câu lệnh sau trở thành
  • while ((0 & (1 << 13)) == 0);
  • Tức là while (1);
  • Vòng này đương nhiên không bao giờ dừng lại => Fail.
    💬 Còn một vấn đề nữa là các thanh ghi của PORT / GPIO thường chỉ cho phép access theo Word, nên khi chúng ta cố gắng access theo Byte mà không có keyword "volatile", chúng sẽ bị optimize thành lệnh không được cho phép (là access theo byte), từ đó sẽ sinh ra các lỗi khó nhận biết (Mình sẽ có video hướng dẫn sau).

    👉 Chương trình con phục vụ ngắt (ISR)

    Ngắt thường xuyên được sử dụng trong nhúng, ngắt ngoài, ngắt UART, SPI, Timer, ...

    Trường hợp biến toàn cục (global) bị thay đổi trong chương trình con phục vụ ngắt, và trong main có sử dụng biến này.

    Ví dụ (Trong hình 2):

  • Một biến Global_Check bị thay đổi trong ngắt UART, trong hàm main() đang dùng nó cho vòng while.
  • Ở đây không có volatile nên Compiler không biết được biến Global_Check này có thể thay đổi trong ngắt.
  • Vòng while trong main() sẽ optimize thành while(1) -> Fail.

    👉 Các ứng dụng đa luồng

    Giống như trường hợp ISR, các biến toàn cục dùng trong nhiều tác vụ trong các ứng dụng đa luồng có thể bị thay đổi trong các Task khác nhau.

    Ví dụ (trong hình 3) biến Global_Check có thể bị optimize nếu không được khai báo Volatile.

    😁 Các bạn lập trình các vi điều khiển 8-bits sẽ ít gặp các trường hợp này, có thể test bằng cách vào IDE và bật Optimize lên, hoặc sửa Compiler Option trong Makefile. Các dòng 32-bits thì cần chú ý dùng rất nhiều!

>>>= Follow ngay =<<<

💚 Kênh Youtube Lập trình - Điện tử 💚

Để nhận được những bài học miễn phí mới nhất nhé 😊

Đăng nhận xét

0 Nhận xét