Trong lập trình nhúng, chúng ta thường gặp từ khóa “volatile” khi khai báo biến. Từ khóa này rất cần thiết để tránh những lỗi khó phát hiện do tính năng optimization của compiler. Trong bài viết này, chúng ta sẽ tìm hiểu ý nghĩa của từ khóa này, cách sử dụng và lý do tại sao nó quan trọng trong lập trình với hệ thống nhúng và ứng dụng đa luồng.
Ý nghĩa và cách sử dụng từ khóa volatile
Một biến cần được khai báo dưới dạng biến “volatile” khi giá trị của nó có thể thay đổi một cách không báo trước. Thực tế có 3 loại biến có giá trị có thể bị thay đổi như vậy:
- Memory-mapped peripheral registers: Đây là các thanh ghi ngoại vi có ánh xạ đến ô nhớ.
- Biến toàn cục được truy xuất từ các tiến trình con xử lý ngắt (interrupt service routine).
- Biến toàn cục được truy xuất từ nhiều tác vụ trong một ứng dụng đa luồng.
Các thanh ghi ngoại vi
Trong các hệ thống nhúng, chúng ta thường gặp các thiết bị ngoại vi như GPIO, UART, SPI, … và các thiết bị này chứa các thanh ghi có giá trị có thể thay đổi ngoài ý muốn của chương trình. Ví dụ, khi ta cần kiểm tra giá trị của một thanh ghi trạng thái pStatReg đến khi nó khác 0, việc sử dụng từ khóa “volatile” đảm bảo rằng giá trị được đọc sẽ luôn là giá trị mới nhất.
Tiến trình con xử lý ngắt (Interrupt Service Routine)
Ngắt là một khái niệm quan trọng trong hệ thống nhúng. Mỗi khi xảy ra ngắt, stack pointer sẽ nhảy đến chương trình con xử lý ngắt (ISR). Thường thì các chương trình con xử lý ngắt này sẽ thay đổi giá trị của biến toàn cục và trong chương trình chính sẽ đọc những giá trị này để xử lý. Việc sử dụng từ khóa “volatile” đảm bảo rằng compiler sẽ kiểm tra giá trị của biến toàn cục này.
Ứng dụng đa luồng
Trong các ứng dụng đa luồng, chúng ta thường xảy ra trường hợp các tác vụ trao đổi thông tin với nhau thông qua một biến toàn cục. Việc sử dụng từ khóa “volatile” đảm bảo rằng compiler sẽ không loại bỏ những phần code liên quan đến biến toàn cục này khi bật tính năng optimization.
Với việc sử dụng từ khóa “volatile”, chúng ta có thể đảm bảo rằng chương trình C sẽ luôn đọc lại giá trị của các biến mà không có những giả định từ compiler. Điều này rất quan trọng trong lập trình nhúng và đảm bảo tính chính xác và đáng tin cậy của hệ thống.