Làm thế nào để thực sự thu nhỏ một bản phác thảo


9

Tôi muốn tạo một bản phác thảo nhỏ nhất có thể, cho mục đích thử nghiệm. Vấn đề là, khi tôi biên dịch bản phác thảo BareMinimum (với một thiết lập và vòng lặp trống), tôi nhận được 466 byte cho Uno và một con số khổng lồ 4.242 cho Leonardo. Có cách nào để viết mã của riêng bạn mà không có chức năng bổ sung (cụ thể là Timer0 cho millis()delay()). Tôi cũng muốn có thể vô hiệu hóa các chức năng bàn phím / chuột cho Leonardo.


4
Không nên gắn thẻ leonardo và không uno (và tập trung vào một bảng)? Đây là những câu hỏi riêng biệt.
asheeshr

Tôi chỉ chỉ ra rằng một bản phác thảo được biên soạn trống rất lớn cho nhiều bảng, đặc biệt là các bản gốc dựa trên USB
TheDoctor

Tôi cũng muốn có thể vô hiệu hóa các chức năng bàn phím / chuột cho Leonardo. là câu hỏi thứ hai.
asheeshr

Câu trả lời:


3

Bạn sẽ có thể tạo định nghĩa bảng của riêng mình với tệp bảng.txt tùy chỉnh theo https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specifying . Như tôi thấy có một số tính năng usb trong định nghĩa của leonardo. Tôi hy vọng rằng việc biên dịch bao gồm 4K dựa trên các cờ này chứ không phải loại bộ xử lý.

Trong đó các bảng.txt sẽ sử dụng các phần tải lên, bộ nạp khởi động từ Leonardo và bản dựng từ uno.

Đây là tất cả giả sử xây dựng thư viện lõi không sử dụng cờ cụ thể của bộ xử lý để bao gồm các chức năng USB.

Nếu bạn làm việc như vậy. gửi lại, tôi chắc chắn những người khác sẽ quan tâm như vậy.


Gần đây tôi đã gặp phải giới hạn sử dụng 4K này trên bản demo thư viện thực sự đã tối đa hóa UNO và phải đưa vào

#if !defined(__AVR_ATmega32U4__)
...

xung quanh một khối lớn các tính năng bổ sung trong bản phác thảo để phù hợp với Leonardo.

Tôi đã giả định (sai) rằng 4K này là bởi vì tôi vẫn bao gồm Serial.print mà khi qua CDC của USB trên Leo. Nhưng tôi thấy sau một đống ký ức về một bản phác thảo trống rỗng, chúng vẫn còn đó.

C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst

Mà có ý nghĩa. Vì Leonardo vẫn yêu cầu máy khách USB-CDC (4K) để phát hiện kết nối 1200 Baud từ AVR-DUDE để thực hiện khởi động lại từ xa.


Do đó, tạo một bảng tùy chỉnh không có USB trong bản dựng, cũng cần phải có

leonardo.upload.use_1200bps_touch=true

loại bỏ.

Sau khi được tải vào mục tiêu, điều này sẽ yêu cầu tải lên phải được đồng bộ hóa với cài đặt lại thủ công của mục tiêu. Khi khả năng khởi động lại từ xa bị mất.


được cập nhật về lý do 4K vẫn được biên dịch, ngay cả khi Serial.print bị bỏ qua.
mpflaga

3

Gần đây tôi muốn làm chính xác điều này. Vì không có cách nào hay để làm như vậy, tôi đã viết ra một bản vá cho plugin arduino siêu văn bản Stino để làm chính xác điều này. Sau đó, nó đã được chấp nhận, do đó, nó sẽ có trong bất kỳ bản cài đặt Stino cập nhật nào.

Điều này thêm một tùy chọn mới cho Stino:

nhập mô tả hình ảnh ở đây

Sử dụng chế độ này tạo ra kết quả biên dịch như sau:

Đối với một Uno:

Kích thước phác thảo nhị phân: 172 byte (tối đa 32256 byte, 0,53%).
Sử dụng bộ nhớ ước tính: 0 byte (tối đa 1024 byte, 0,00 phần trăm).

Cho một leonardo

Kích thước phác thảo nhị phân: 240 byte (tối đa 28672 byte, 0,84 phần trăm).
Sử dụng bộ nhớ ước tính: 0 byte (tối đa 2560 byte, 0,00 phần trăm).

Trên thực tế, lập trình leonardo với đầu ra được biên dịch ở trên có lẽ là một ý tưởng tồi, vì nó có thể phá vỡ chức năng tự động đặt lại, nhưng bạn có thể , nếu bạn muốn. Hat-tip cho mpflaga vì đã lưu ý điều này trong câu trả lời của anh ấy.

Lưu ý rằng các báo cáo bộ nhớ thực sự không chính xác, nhưng đó là một vấn đề riêng biệt .

Mã được sử dụng cho ở trên là:

int main()
{
    while (1)
    {

    }
}

Một số lưu ý:

  • Bạn không được viết một "Phác thảo" nữa, không phải là bạn đã bao giờ thực sự làm viết một bản phác thảo. Bạn viết chương trình . Giai đoạn = Stage. Tôi không quan tâm những gì các wackos Arduino muốn nói, họ không được xác định lại các điều khoản.
  • Tất cả quản lý ngắt là thủ công. Điều này có nghĩa là không milis()hoặc tương tự.
  • Bạn vẫn có thể sử dụng các thư viện nối tiếp arduino và vv, nếu bạn muốn. Bạn phải làm #include <Arduino.h>.
  • Bạn xác định main. Bạn không bao giờ trở về từ main. Nếu bạn muốn thiết lập công cụ, nó đi trước while (1).

@jfpoilpret Bạn gọi đó là IDE? Giống như notepad với macro ...
Ron

@ Ron-E Tôi không gọi nó là IDE, Arduino IDE là tên của nó, vì vậy tôi chỉ sử dụng tên của nó, mặc dù nó không xứng đáng với tên đó.
jfpoilpret

2
@FakeName Ngôn ngữ xấu không được phép trên các trang web Stack Exchange (xem: stackoverflow.com/help/behavior ). Tôi đã chỉnh sửa nó trong trường hợp này, nhưng vui lòng cố gắng không sử dụng thám hiểm trên trang web này trong tương lai. Cảm ơn.
Peter Bloomfield

2

Mặc dù nó phụ thuộc vào bản phác thảo của bạn, bạn có thể giảm phần nào kích thước bằng cách sử dụng lại mã với các phương thức.

Lấy mã này:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  val = digitalRead(10);
}

1.322 byte trên Arduino Uno. Bây giờ hãy thu nhỏ nó lại một chút:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  for(uint8_t i = 0; i < 8; i++) {
    blink(HIGH);
    blink(LOW);
  }    
  val = digitalRead(10);
}

void blink(uint8_t state) {
  digitalWrite(led, state);   // turn the LED to the right state
  delay(1000);                // wait for a second
}

1.194 byte. Đó là giảm 10%!

Dù sao, mặc dù nó không đáng kể thu nhỏ một phác thảo, đôi khi có thể là con đường dễ dàng nhất khi bạn đang ở hai byte vượt quá giới hạn, hoặc chỉ muốn thực hiện một phác thảo nhỏ gọn hơn để bắt đầu với mà không mất bất kỳ chức năng. Nó không phải cho mọi tình huống, nhưng đôi khi tôi thấy nó hữu ích.


Nói chung, nếu bạn kéo mã ra thành các hàm, trình biên dịch sẽ thực hiện công việc khó khăn và lấy phần còn lại phù hợp với bạn.
Cyberg Ribbon

@Cyberg Ribbon Bạn có thể xác định rằng [đối với người dùng không quen thuộc với điều đó]?
Chim cánh cụt vô danh

3
Nếu bạn chia mã thành một hàm và nó không hiệu quả, thông thường trình biên dịch sẽ sắp xếp nó cho bạn. Tuy nhiên, một trình biên dịch sẽ không bao giờ phá vỡ mã thành các hàm. Do đó, gần như luôn luôn tốt hơn để viết nhiều chức năng hơn.
Cyberg Ribbon

1
Cộng với việc đặt mã vào các chức năng giúp đọc và hiểu dễ dàng hơn nhiều

Sử dụng truy cập cổng trực tiếp, kích thước được giảm xuống còn 646 byte. Chỉ sử dụng avr-libc (không có lõi Arduino), nó sẽ giảm xuống còn 220 byte.
Edgar Bonet

0

@annonomus chim cánh cụt, chắc chắn chúng ta có thể Mặc dù mã biên dịch thành 1180 byte flash + 13 byte RAM cho một máy tính của tôi, chúng tôi có thể cải thiện nó :) vì vậy, thách thức golf được chấp nhận và một vài mẹo hữu ích vì chúng tôi đang kinh doanh học tập.

Bước 1: giảm yêu cầu biến. Sử dụng một int cho một cổng led có vẻ hơi quá mức, chúng tôi chắc chắn không có 65535 cổng IO có thể định địa chỉ trên arduino :) Vì vậy, chúng tôi thay đổi nó thành một byte chỉ để cho vui. Chúng tôi sẽ thay đổi nó thành #define sau này, nhưng để cho thấy tác động của việc sử dụng các loại biến quá lớn.

byte led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Biên dịch thành 1172 byte + RAM 13 byte. Điều này giúp tiết kiệm 8 byte flash do ít thao tác cần thiết hơn cho byte thay vì số nguyên. Tôi sẽ mong đợi 12 byte ram, nhưng không sao. Không nhiều, nhưng mỗi byte được lưu là tốt.

Bước 2: thay đổi biến thành định nghĩa khi nó có ý nghĩa. Ví dụ, byte dẫn là không cần thiết, pin sẽ không tự hàn.

#define LED 13
int val;

void setup() {                
  pinMode(LED, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Biên dịch thành 1142 byteflash + 11 byte ram. Đã lưu 38 byte. Điều này là do ít hoạt động đăng ký cần thiết để lấy giá trị int. Ngoài ra, chúng tôi đã lưu 2 byte từ RAM. (vẫn thắc mắc tại sao byte không biên dịch thành 1 byte ram ít hơn .....)

Bước 3: tối ưu hóa mã. Tôi thấy 2 sự chậm trễ. Tôi tự hỏi nếu tôi thay đổi nó thành 1 độ trễ thì nó sẽ tiết kiệm không gian, nhưng tôi phải tìm ra giá trị của chân LED và chuyển đổi (đảo ngược) nó. Chúng ta có thể làm điều đó với digitalRead (), nhưng nó có tiết kiệm không gian không?

#define LED 13
int val;
void setup() {                
  pinMode(LED, OUTPUT);     
}
void loop() {
  blink();
  val = digitalRead(10);
}
void blink() {
  digitalWrite(LED, !digitalRead(LED));   // toggle the led based on read value
  delay(1000);               // wait for a second and spare yourself the other delay
}

Biên dịch thành 1134 byte + 11 byte ram. Yay! 8 byte khác. Điều đó làm cho tổng cộng 46 byte và ít hơn 2 dòng mã.

Ngoài ra một mẹo chung khác về giảm mã hóa. Đừng sử dụng lớp String. Đó là LỚN, tìm hiểu cách xử lý các mảng char, strcpy (), strcmp (). Nếu tất cả những gì bạn có là một số thao tác chuỗi cơ bản, việc sử dụng lớp String chủ yếu chỉ làm lãng phí không gian trên cả flash và RAM.

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.