Bạn cần vô hiệu hóa ngắt để đảm bảo truy cập nguyên tử. Bạn không muốn bất kỳ quy trình nào khác truy cập và có khả năng sửa đổi biến đó khi bạn đang đọc nó.
Từ Introduction to Embedded Computing:
Nhu cầu truy cập Atomic
Hãy tưởng tượng kịch bản này: Chương trình foreground, chạy trên một 8-bit UC, nhu cầu để kiểm tra một biến 16-bit, gọi nó là X Vì vậy, nó tải cao byte và sau đó tải byte thấp (hoặc cách khác xung quanh, thứ tự không quan trọng), và sau đó kiểm tra giá trị 16-bit. Bây giờ hãy tưởng tượng một ngắt với một ISR liên quan để sửa đổi biến 16 bit đó. Hãy tưởng tượng thêm rằng giá trị của biến xảy ra là 0x1234 tại một thời gian nhất định trong quá trình thực thi chương trình. Dưới đây là Very Bad Thing có thể xảy ra:
- tải foreground byte cao (0x12)
- ISR xảy ra, sẽ thay đổi X để 0xABCD
- tải foreground byte thấp (0xCD)
- chương trình foreground thấy giá trị 16 bit của 0x12CD.
Vấn đề là một mảnh được cho là bất khả phân của dữ liệu, biến X của chúng tôi, thực sự đã được sửa đổi trong quá trình truy cập vào nó, vì các hướng dẫn CPU để truy cập biến là chia hết cho. Và do đó tải của chúng tôi về biến X đã bị hỏng. Bạn có thể thấy rằng thứ tự của biến đọc không quan trọng. Nếu đơn đặt hàng được đảo ngược trong ví dụ của chúng tôi, biến sẽ không được đọc sai dưới dạng 0xAB34 thay vì 0x12CD. Dù bằng cách nào, giá trị được đọc không phải là giá trị hợp lệ cũ (0x1234) hoặc giá trị hợp lệ mới (0xABCD).
Viết dữ liệu tham chiếu ISR không tốt hơn. Thời gian này giả định rằng chương trình tiền cảnh đã được viết, vì lợi ích của ISR, giá trị trước đó là 0x1234 và sau đó cần phải viết một giá trị 0xABCD mới.Trong trường hợp này, VBT được như sau:
- cửa hàng foreground mới byte cao (0xAB)
- ISR xảy ra, đọc X như 0xAB34
- cửa hàng foreground mới byte thấp (0xCD)
Một lần nữa mã (lần này là ISR) không thấy giá trị hợp lệ trước đây là 0x1234, cũng như giá trị hợp lệ mới của 0xABCD, nhưng thay vì giá trị không hợp lệ của 0xAB34.
Trong khi spiTxRxByteCount &= ~0x0100;
có thể trông giống như một hướng dẫn trong C, thực ra nó là một vài hướng dẫn cho CPU. Biên soạn trong GCC, việc niêm yết lắp ráp trông giống như vậy:
57:atomic.c **** spiTxRxByteCount &= ~0x0100;
68 .loc 1 57 0
69 004d A1000000 movl _spiTxRxByteCount, %eax
69 00
70 0052 80E4FE andb $254, %ah
71 0055 A3000000 movl %eax, _spiTxRxByteCount
71 00
Nếu một ngắt được lấy ở giữa bất kỳ của những hướng dẫn và sửa đổi các dữ liệu, ISR đầu tiên của bạn có khả năng có thể đọc các giá trị sai. Vì vậy, bạn cần phải vô hiệu hóa ngắt trước khi bạn hoạt động trên nó và cũng tuyên bố biến volatile
.
Nếu bạn có RTOS, tại sao không sử dụng mutex? –
@ [Hoạt động semaphore được thực hiện theo cách này trong hệ điều hành] (http://www.mpi-sws.org/~druschel/courses/os/lectures/proc4.pdf) –