Theo dõi chu kỳ đồng hồ cho mã trên arduino / AVR?


11

Có thể giám sát một khối mã và xác định số chu kỳ xung nhịp của bộ xử lý mà mã đã sử dụng trên bộ xử lý Arduino và / hoặc AVR atmel không? hoặc, tôi có nên theo dõi micro giây được truyền trước và sau khi chạy mã không? Lưu ý: Tôi không quan tâm đến thời gian thực (ví dụ như, có bao nhiêu giây thực đã trôi qua) nhiều như tôi đang ở "mã này yêu cầu bao nhiêu chu kỳ xung nhịp từ CPU"

Giải pháp hiện tại tôi có thể đưa ra là từ time.c:

#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )

hệ thống dây điện cho biết thêm:

#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )

Bằng tài khoản này, tôi có thể tính toán các kiểu đồng hồ được truyền bằng cách theo dõi micro giây được truyền và sau đó chuyển nó sang microsecondsToClockC đua (). Câu hỏi của tôi là, có cách nào tốt hơn không?

sidenote: có các nguồn lực tốt để giám sát hiệu suất của AVR. lmgtfy.com và các tìm kiếm diễn đàn khác nhau không cung cấp bất kỳ kết quả rõ ràng nào, ngoài việc khám phá bộ tính giờ

cảm ơn

Câu trả lời:


6

Phương pháp đơn giản nhất là làm cho mã của bạn kéo một số pin lên trước khi nó thực thi mã bạn muốn thời gian và kéo nó xuống thấp sau khi nó đã hoàn thành bất cứ việc gì. Sau đó thực hiện vòng lặp mã (hoặc sử dụng máy hiện sóng kỹ thuật số với bộ nhớ ở chế độ chụp một lần) và chỉ phạm vi sau đó ghim. Độ dài của xung cho bạn biết phải mất bao lâu để thực thi đoạn mã cộng với một chu kỳ xung nhịp từ việc thay đổi trạng thái pin (tôi nghĩ rằng nó mất một chu kỳ, không chắc chắn 100%).


Cảm ơn. Vâng, tôi có thể thấy đây có lẽ là giải pháp chính xác nhất. Tôi vẫn đang sử dụng mã sẽ cung cấp cho tôi ít nhất là phân tích sử dụng chu kỳ chung trong mã. Tôi sẽ sử dụng công cụ này để xây dựng một số công cụ kiểm tra và thật tuyệt khi đặt giới hạn trên của mình cho các tham số như thời gian chạy tối đa được phép dựa trên mức độ hiệu quả của mã + mọi thứ liên quan đến nó đang chạy trên CPU Atmel hiện tại sử dụng
cyphunk

4

"Màn hình" nghĩa là gì?

Không khó để đếm chu kỳ xung nhịp cho AVR cho các đoạn mã lắp ráp nhỏ.

Bạn cũng có thể đặt một cổng trước khi mã được thực thi và đặt lại sau đó, và theo dõi cổng đó bằng máy phân tích logic hoặc máy đo thẩm thấu để lấy thời gian.

Và bạn cũng có thể đọc thời gian từ một bộ đếm thời gian chạy nhanh, như bạn nói.


Bằng cách theo dõi tôi có nghĩa là xác định số lượng chu kỳ được sử dụng bởi mã. một cái gì đó như (lưu ý, định dạng mã có thể sẽ được làm phẳng bằng công cụ bình luận): clock = startCountingAtmegaClocks (); for ... {for ... {digitalRead ...}} serial.print ("num chu kỳ đã sử dụng:"); Serial.print (currentCountingAtmegaClocks () - đồng hồ, DEC);
cyphunk

Nhưng vâng, phản hồi của bạn là những gì tôi đã giả định lựa chọn của mình. Tôi đoán, tôi giả sử nếu tôi có thể tính toán chu kỳ đồng hồ thì trình biên dịch sẽ lấy bằng tay rằng ai đó có lẽ đã viết một số mã đẹp để thực hiện việc này theo chương trình
cyphunk

3

Đây là một ví dụ cho Arduino sử dụng hàm clockC đuaPerMicrosecond () để tính toán các đồng hồ đã qua. Mã này sẽ đợi 4 giây, sau đó in thời gian đã trôi qua kể từ khi bắt đầu chương trình. 3 giá trị còn lại là tổng thời gian (micro giây, mili giây, tổng chu kỳ đồng hồ) và hầu hết 3 phải là thời gian trôi qua:

Đầu ra:

clocks for 1us:16
runtime us, ms, ck :: elapsed tme us, ms ck
4003236 4002	64051776	::	4003236	4002	64051760
8006668 8006	128106688	::	4003432	4004	64054912
12010508    12010	192168128	::	4003840	4004	64061440
16014348    16014	256229568	::	4003840	4004	64061440
20018188    20018	320291008	::	4003840	4004	64061440
24022028    24022	384352448	::	4003840	4004	64061440
28026892    28026	448430272	::	4004864	4004	64077824
32030732    32030	512491712	::	4003840	4004	64061440
36034572    36034	576553152	::	4003840	4004	64061440
40038412    40038	640614592	::	4003840	4004	64061440
44042252    44042	704676032	::	4003840	4004	64061440
48046092    48046	768737472	::	4003840	4004	64061440
52050956    52050	832815296	::	4004864	4004	64077824

Tôi chắc chắn có một lời giải thích hợp lý tại sao các vòng lặp đầu tiên có chu kỳ đồng hồ trôi qua ngắn hơn hầu hết và tại sao tất cả các vòng lặp khác chuyển đổi giữa hai độ dài của chu kỳ đồng hồ.

Mã số:

unsigned long us, ms, ck;
unsigned long _us, _ms, _ck;
unsigned long __us, __ms, __ck;
void setup() {
        Serial.begin(9600);
}
boolean firstloop=1;
void loop() { 
        delay(4000);

        if (firstloop) {
                Serial.print("clocks for 1us:");
                ck=microsecondsToClockCycles(1);
                Serial.println(ck,DEC);
                firstloop--;
                Serial.println("runtime us, ms, ck :: elapsed tme us, ms ck");
        }

        _us=us;
        _ms=ms;
        _ck=ck;

        us=micros(); // us since program start
        ms=millis();
        //ms=us/1000;
        ck=microsecondsToClockCycles(us);
        Serial.print(us,DEC);
        Serial.print("\t");
        Serial.print(ms,DEC);
        Serial.print("\t");
        Serial.print(ck,DEC);     
        Serial.print("\t::\t");

        __us = us - _us;
        __ms = ms - _ms;
        __ck = ck - _ck;
        Serial.print(__us,DEC);
        Serial.print("\t");
        Serial.print(__ms,DEC);
        Serial.print("\t");
        Serial.println(__ck,DEC);     

}

Sidenote: nếu bạn loại bỏ độ trễ 4 giây, bạn sẽ bắt đầu thấy các hiệu ứng của Serial.print () rõ ràng hơn nhiều. Lưu ý, ở đây 2 lần chạy được so sánh. Tôi chỉ bao gồm 4 mẫu gần nhau từ nhật ký tương ứng của họ.

Chạy 1:

5000604 5000	80009664	::	2516	2	40256
6001424 6001	96022784	::	2520	3	40320
7002184 7002	112034944	::	2600	3	41600
8001292 8001	128020672	::	2600	3	41600

Chạy 2:

5002460 5002	80039360	::	2524	3	40384
6000728 6000	96011648	::	2520	2	40320
7001452 7001	112023232	::	2600	3	41600
8000552 8000	128008832	::	2604	3	41664

Thời gian trôi qua tăng trên tổng thời gian chạy. Sau một giây trôi qua, đồng hồ tăng trung bình từ 40k lên 44k. Điều này xảy ra liên tục vài mili giây sau 1 giây và đồng hồ đã trôi qua vẫn còn khoảng 44k trong ít nhất 10 giây tiếp theo (tôi chưa thử nghiệm thêm). Đây là lý do tại sao giám sát là hữu ích hoặc cần thiết. Có lẽ hiệu quả giảm có liên quan đến cấu hình hoặc lỗi nối tiếp? Hoặc có lẽ mã không sử dụng đúng bộ nhớ và bị rò rỉ ảnh hưởng đến hiệu suất, v.v.


nhiều năm sau, tôi vẫn muốn một cái gì đó hiển thị đồng hồ chính xác hơn bằng mã (như được gắn với máy hiện sóng). Tại tôi đang cố gắng xác định số chu kỳ đồng hồ cần thiết cho một DigitalWrite () trong cả 16MHZ và 8MHZ. Trong 16MHZ tôi nhận được 8us / 64clk. Nhưng trong 8MHZ tôi nhận được 0us / 0clk.
cyphunk

1

Vì mỗi dòng mã được thêm vào nguồn của bạn sẽ có tác động đến hiệu suất và có thể thay đổi tối ưu hóa được áp dụng. Các thay đổi phải là mức tối thiểu cần thiết để thực hiện nhiệm vụ.

Tôi vừa tìm thấy một plugin Atmel Studio có tên là "Trình gỡ lỗi tệp hội thảo chú thích". http://www.atmel.com/webdoc/aafdebugger/pr01.html Có vẻ như bước qua ngôn ngữ lắp ráp được tạo thực tế trong khi có lẽ tẻ nhạt sẽ cho bạn thấy chính xác những gì đang xảy ra. Bạn vẫn có thể phải giải mã bao nhiêu chu kỳ cho mỗi hướng dẫn nhưng nó sẽ tiến gần hơn rất nhiều so với một số tùy chọn được đăng khác.

Đối với những người không biết trong thư mục đầu ra của dự án của bạn là một tệp có phần mở rộng LSS. Tệp này chứa tất cả mã nguồn gốc của bạn dưới dạng nhận xét và bên dưới mỗi dòng là ngôn ngữ lắp ráp được tạo dựa trên dòng mã đó. Tạo tập tin LSS có thể được tắt để kiểm tra cài đặt sau.

Thuộc tính dự án | Công cụ | AVR / GNU Chung | Kết quả đầu ra

Hộp kiểm ".lss (Tạo tệp lss)


1

Bạn có thể sử dụng một trong các bộ định thời tích hợp. Nhận mọi thứ được thiết lập cho prescaller = 1 và TCNT = 0 trước khối. Sau đó kích hoạt bộ hẹn giờ trên dòng trước khối và vô hiệu hóa nó trên dòng sau khối. TCNT hiện sẽ giữ số chu kỳ mà khối đã thực hiện, trừ các chu kỳ cố định cho mã kích hoạt và vô hiệu hóa.

Lưu ý rằng TNCT sẽ tràn sau 65535 chu kỳ xung nhịp trên bộ hẹn giờ 16 bit. Bạn có thể sử dụng cờ tràn để tăng gấp đôi thời gian chạy. Nếu bạn vẫn cần lâu hơn, bạn có thể sử dụng một bộ đếm gộp trước, nhưng sẽ có độ phân giải ít hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.