2016-08-22 11 views
7

Đôi khi tôi cần một số mã được CPU thực thi chính xác như khi tôi đặt nó vào nguồn. Nhưng bất kỳ trình biên dịch C nào cũng có các thuật toán tối ưu hóa của nó để tôi có thể mong đợi một số thủ thuật. Ví dụ:Làm cách nào để "thông báo" cho trình biên dịch C rằng mã không được tối ưu hóa?

unsigned char flag=0; 

interrupt ADC_ISR(){ 
    ADC_result = ADCH; 
    flag = 1; 
} 

void main(){ 
    while(!flag); 
    echo ADC_result; 
} 

Một số trình biên dịch chắc chắn sẽ làm cho while(!flag); loop infinitive vì nó sẽ giả sử flag bằng false (!flag do đó phải luôn luôn đúng).

Thỉnh thoảng tôi có thể sử dụng từ khóa volatile. Và đôi khi nó có thể giúp đỡ. Nhưng thực tế trong trường hợp của tôi (AVR GCC) volatile trình biên dịch lực từ khóa để định vị biến vào SRAM thay vì các thanh ghi (điều này có hại vì một số lý do). Hơn nữa, nhiều bài viết trên Internet gợi ý sử dụng từ khóa volatile với sự quan tâm lớn vì kết quả có thể trở nên không ổn định (tùy thuộc vào trình biên dịch, cài đặt tối ưu hóa, nền tảng, v.v.).

Vì vậy, tôi chắc chắn sẽ thích bằng cách nào đó chỉ ra hướng dẫn mã nguồn và nói với trình biên dịch rằng mã này nên được biên dịch chính xác như nó được. Như thế này: volatile while(!flag);

Có bất kỳ hướng dẫn C chuẩn nào để thực hiện việc này không?

+1

Tất nhiên biến 'biến động' sẽ chuyển sang RAM! Đăng ký là dành cho các giá trị tạm thời, Một gián đoạn có thể xảy ra bất cứ lúc nào. Tôi muốn khuyên bạn nên làm một số nghiên cứu thêm về đồng thời, đặc biệt là xử lý ngắt và phát triển phần mềm nhúng.Ví dụ cho một cờ boolean, bạn nên sử dụng kiểu chuẩn boolean. – Olaf

+1

Dễ bay hơi có nghĩa là giá trị biến không thể được lưu trữ giữa các lần đọc (và các ghi đó không thể di chuyển xung quanh). Có, điều đó thường dẫn đến việc giảm tải vào RAM mỗi lần. Nếu bạn nghĩ rằng bạn có thể làm tốt hơn thế, bạn nên thử [inline assembly] (http://www.ethernut.de/en/documents/arm-inline-asm.html). – Cubic

+0

@Cubic: Thay đổi nội tuyến sẽ làm gì cho các biến? OP dường như thậm chí không suy nghĩ về mã được tối ưu hóa kém, nhưng sử dụng tài nguyên. Giải pháp duy nhất cho việc này là viết ** mọi thứ ** trong Assembler, vì vậy anh ta có thể kiểm soát đăng ký CPU và cấp phát bộ nhớ 100%. Micromanagement tốt nhất của nó. Tôi đã làm điều này trong nhiều năm và tôi rất vui vì chúng tôi có những trình biên dịch quan tâm đến điều này. – Olaf

Trả lời

3

Bạn thực sự nên sử dụng volatile làm answered by David Schwartz. Xem thêm this chương của tài liệu GCC.

Nếu bạn sử dụng một trình biên dịch GCC gần đây, bạn có thể vô hiệu hóa tối ưu hóa trong một chức năng duy nhất bằng cách sử dụng thích hợp function specific options pragmas (hoặc một số chức năng optimizeattribute), ví dụ

#pragma GCC optimize ("-O0"); 

trước main của bạn. Tôi không chắc đó là một ý hay.

Có lẽ bạn muốn extended asm statements with the volatile keyword.

8

Cách C tiêu chuẩn duy nhất là volatile. Nếu điều đó không xảy ra để làm chính xác những gì bạn muốn, bạn sẽ cần phải sử dụng một cái gì đó cụ thể cho nền tảng của bạn.

+0

Không cần thiết cho một cái gì đó "đặc biệt". – Olaf

1

Bạn có một vài lựa chọn:

  1. Compile mà không optimisations. Không giống như một số trình biên dịch, GCC không tối ưu hóa theo mặc định, trừ khi bạn yêu cầu nó tối ưu hóa, bạn sẽ nhận được mã được tạo trông rất giống với nguồn C của bạn. Tất nhiên bạn có thể chọn tối ưu hóa một số tệp C chứ không phải các tệp khác, bằng cách sử dụng quy tắc đơn giản.

  2. Lấy trình biên dịch ra khỏi phương trình và viết các hàm có liên quan trong assembly. Sau đó, bạn có thể nhận được chính xác mã được tạo mà bạn muốn.

  3. Sử dụng dễ bay hơi, ngăn cản trình biên dịch đưa ra bất kỳ giả định nào về một biến nhất định, do đó, khi sử dụng biến trong trình biên dịch C buộc phải tạo LOAD hoặc STORE ngay cả khi không cần thiết.

Các vấn đề liên quan