Sumberdaya tentang Menulis Kode C yang Efisien untuk Pengontrol Mikro? [Tutup]


15

Dibutuhkan bantuan serius di sini. Saya suka pemrograman. Saya telah membaca banyak buku (seperti K&R) dan artikel / forum online untuk bahasa C belakangan ini. Bahkan mencoba melihat ke dalam kode Linux (walaupun, saya tidak tahu harus mulai dari mana tetapi mengintip ke perpustakaan kecil membantu?).

Saya mulai sebagai programmer Java dan di Jawa itu cukup memotong dan kering; Jika program menjadi terlalu besar, iris di kelas kemudian lanjut ke fungsi. Pedoman seperti, menjaga kode dibaca dan menambahkan komentar. Gunakan teknik penyembunyian informasi dan OOP. Beberapa di antaranya masih berlaku untuk C.

Saya telah mengkode dalam C sekarang dan sejauh ini saya mendapatkan program untuk bekerja dengan satu atau lain cara. Banyak orang berbicara tentang kinerja / efisiensi, algoritma / desain, optimisasi, dan pemeliharaan. Beberapa orang menekankan satu lebih dari yang lain tetapi untuk insinyur perangkat lunak non-profesional Anda sering mendengar sesuatu seperti misalnya: Linux kernel dev tidak hanya akan mengambil kode apa pun.

Pertanyaan saya adalah ini: Saya berencana menulis kode untuk mikrokontroler 8-bit tanpa membuang sumber daya apa pun . Ketahuilah bahwa saya berasal dari latar belakang java sehingga semuanya tidak sama lagi ... sumber daya / buku / tautan / tips akan sangat dihargai. Kinerja dan ukuran sekarang penting. Sumber daya / Trik pada kode C efisien (dalam praktik terbaik) untuk pengontrol mikro 8-bit?

Juga, inline assemblymemainkan peran penting juga menempel dekat dengan standar pengontrol mikro. Tetapi adakah aturan umum untuk efisiensi yang berlaku untuk semua?

Misalnya: register unsigned int variable_name;lebih disukai daripada charkapan saja. Atau menggunakan uint8_t jika Anda tidak membutuhkan angka besar.

EDIT: Terima kasih banyak atas semua jawaban dan sarannya. Saya menghargai upaya semua orang untuk berbagi pengetahuan.


2
Ini tidak sering terjadi pada prosesor x86, tetapi pada mikrokontroler, jika Anda ingin memastikan Anda mendapatkan setiap tetes kinerja terakhir, Anda mungkin ingin menggunakan perakitan.
Rei Miyasaka

3
@Rei: Majelis kerajinan tangan jarang, jika pernah, menggunakan lebih sedikit memori dan lebih cepat daripada kompiler C modern. Buang-buang waktu untuk menyusun kode ketika dapat (sebagaimana mestinya) dilakukan dalam C.
mattnz

1
@ mattnz Secara modern, seberapa baru Anda membicarakannya? Sejujurnya saya belum menulis kode untuk mikrokontroler dalam hampir satu dekade.
Rei Miyasaka

2
Satu tip sederhana: dalam kontrol mikron, umumnya masih benar bahwa "jika lebih sederhana, lebih cepat". Pada chip yang kompleks (ARM dan yang lebih tinggi), perangkat keras melakukan begitu banyak optimasi yang Anda tidak pernah tahu sampai Anda menguji.
Javier

1
@ReiMiyasaka dengan kenaikan besar biaya perawatan. Kompiler C yang baik dapat menghasilkan kode yang hampir sama dengan programmer yang sangat berpengalaman.

Jawaban:


33

Saya memiliki 20+ tahun sistem embedded, kebanyakan 8 dan 16 micros. Jawaban singkat untuk pertanyaan Anda sama dengan pengembangan perangkat lunak lainnya - jangan optimalkan sampai Anda tahu Anda perlu, dan kemudian jangan optimalkan sampai Anda tahu apa yang perlu Anda optimalkan. Tulis kode Anda sehingga dapat diandalkan, dapat dibaca dan dipelihara terlebih dahulu. Optimalisasi prematur adalah sebanyak, jika tidak lebih dari, masalah dalam sistem embedded

Ketika Anda memprogram "tanpa membuang sumber daya apa pun.", Apakah Anda menganggap waktu Anda sebagai sumber daya? Jika tidak, siapa yang membayar Anda untuk waktu Anda, dan jika tidak ada, apakah Anda ada hubungannya dengan itu. Sekali pilihan setiap perancang sistem tertanam harus membuat adalah biaya perangkat keras vs biaya waktu rekayasa. Jika Anda akan mengirim 100 unit, gunakan mikro yang lebih besar, dengan 100.000 unit, penghematan $ 1,00 per unit sama dengan 1 tahun pengembangan perangkat lunak (mengabaikan waktu ke pasar, biaya peluang, dll.), Dengan 1 Juta unit, Anda mulai mendapatkan ROI karena terobsesi dengan penggunaan sumber daya, tetapi berhati-hatilah karena banyak proyek yang disematkan tidak pernah mencapai angka 1 juta karena mereka dirancang untuk menjual 1 juta (investasi awal yang tinggi dengan biaya produksi rendah), dan bangkrut sebelum mereka sampai di sana.

Yang mengatakan, hal-hal yang perlu Anda perhatikan dan sadari dengan sistem tertanam (kecil), karena ini akan menghentikannya bekerja, dengan cara yang tidak terduga, tidak hanya membuatnya lambat.

a) Stack - Anda biasanya hanya memiliki ukuran tumpukan kecil dan ukuran bingkai tumpukan sering terbatas. Anda harus waspada dengan pemanfaatan tumpukan Anda setiap saat. Hati-hati, masalah tumpukan menyebabkan beberapa cacat paling berbahaya.

b) Heap - lagi, ukuran heap kecil jadi hati-hati tentang alokasi memori yang tidak beralasan. Fragmentasi menjadi masalah. Dengan dua ini, Anda perlu tahu apa yang Anda lakukan ketika Anda kehabisan - itu tidak terjadi pada sistem besar karena OS disediakan paging. yaitu ketika malloc mengembalikan NULL, apakah Anda memeriksanya dan apa yang Anda lakukan. Setiap mallow membutuhkan cek dan penangan, kode mengasapi? Sebagai panduan - jangan menggunakannya jika ada alternatif. Sebagian besar sistem kecil tidak menggunakan memori dinamis karena alasan ini.

c) Gangguan perangkat keras - Anda harus tahu cara menanganinya dengan cara yang aman dan tepat waktu. Anda juga perlu tahu cara membuat kode masuk kembali yang aman. Sebagai contoh, lib standar C umumnya tidak masuk kembali, jadi sebaiknya tidak digunakan di dalam interrupt handler.

d) Majelis - hampir selalu optimasi prematur. Paling sedikit jumlah (inline) diperlukan untuk mencapai sesuatu yang tidak bisa dilakukan C. Sebagai latihan, tulis metode kecil dalam perakitan kerajinan tangan (dari awal). Lakukan hal yang sama dalam C. Ukur kinerja. Saya yakin C akan lebih cepat, saya tahu itu akan lebih mudah dibaca, dipelihara, dan diperpanjang. Sekarang untuk bagian 2 dari latihan - tulis sebuah program yang berguna di assembly dan C.
Sebagai latihan lain, lihat berapa banyak Linux kernal assembler, setelah itu baca, paragraf di bawah ini tentang kernel linux.

Perlu mengetahui cara melakukannya, bahkan mungkin layak untuk mahir dalam bahasa untuk satu atau dua mikroskopi umum.

e) "register unsigned int variable_name", "register" adalah, dan selalu menjadi, petunjuk bagi kompiler, bukan instruksi, pada awal 70-an (40 tahun yang lalu), masuk akal. Pada tahun 2012, ini merupakan pemborosan penekanan tombol karena kompilernya sangat pintar, dan instruksi mikrokompleks sangat kompleks.

Kembali ke komentar linux Anda - masalah yang Anda miliki di sini adalah bahwa kita tidak berbicara hanya 1 juta unit, kita berbicara 100-an juta, dengan waktu hidup selamanya. Waktu dan biaya teknik untuk mendapatkannya seoptimal mungkin secara manusiawi layak dilakukan. Meskipun contoh yang baik dari praktik rekayasa terbaik, itu akan menjadi bunuh diri komersial bagi sebagian besar pengembang sistem embedded untuk menjadi sama hebatnya dengan yang diperlukan linux kernal.


4
mattnz: ini adalah salah satu jawaban terindah di situs .stackexchange.
Ahmed Masud

1
Saya tidak dapat memperbaiki jawaban ini. Saya mungkin hanya menambahkan bahwa memasukkan kode perakitan jarang masuk akal untuk kinerja, tetapi bisa masuk akal untuk hal-hal seperti menusuk chip I / O atau trik perangkat keras lainnya yang mungkin tidak mudah dilakukan di C.
Mike Dunlavey

@mattnz Terima kasih atas jawaban yang dimasukkan +1
AceofSpades

1
@MikeDunlavey assembler terkadang diperlukan untuk pengaturan waktu yang tepat. Baru saja selesai overlay video yang menggunakan bit banging untuk menghasilkan video NTSC pada pin I / O, waktunya adalah dalam hal - tegangan tinggi untuk siklus 3:00, kemudian rendah untuk 6 kemudian ....
Martin Beckett

@ Martin: Itu masuk akal. Sudah lama sejak saya berkode pada tingkat itu.
Mike Dunlavey

3

Pertanyaan Anda ("tanpa membuang sumber daya") terlalu umum, sehingga sulit untuk memberikan banyak saran. Secara harfiah, jika Anda tidak ingin menyia-nyiakan sumber daya, mungkin Anda harus mengambil langkah mundur dan mengevaluasi apakah Anda perlu melakukan apa saja, yaitu, apakah Anda dapat menyelesaikan masalah dengan cara lain.

Juga, saran yang bermanfaat sangat tergantung pada kendala Anda - jenis sistem apa yang Anda bangun dan jenis CPU apa yang Anda gunakan? Apakah ini sistem real-time yang sulit? Berapa banyak memori yang Anda miliki untuk kode dan data? Apakah ini mendukung semua operasi C secara native (terutama, perkalian dan pembagian) dan untuk tipe apa? Lebih umum: membaca seluruh lembar data dan memahaminya .

Saran yang paling penting: tetap sederhana.

Misalnya: lupakan struktur data yang kompleks (hashes, tree, bahkan daftar yang ditautkan) dan gunakan array ukuran tetap. Penggunaan struktur data yang lebih rumit dijamin hanya setelah Anda membuktikan dengan pengukuran bahwa array terlalu lambat.

Juga, jangan overdesign (sesuatu yang cenderung dilakukan oleh Java / C # devs): tulis kode prosedur langsung, tanpa terlalu banyak layering. Abstraksi memiliki biaya!

Dapatkan nyaman dengan ide menggunakan variabel global dan kebagian [sangat berguna untuk pembersihan tanpa adanya pengecualian];)

Jika Anda harus berurusan dengan interupsi, baca tentang reentrancy. Menulis kode reentrant sangat tidak sepele.


3

Saya setuju dengan jawaban mattnz - sebagian besar. Saya mulai pemrograman pada 8085 lebih dari 30 tahun yang lalu, kemudian Z80, kemudian dengan cepat bermigrasi ke 8031. Setelah itu saya pergi ke mikrokontroler seri 68300, kemudian 80x86, XScale, MXL dan (pada akhir) 8 bit PICS, yang saya Dugaan saya berarti lingkaran penuh. Sebagai catatan, saya dapat menyatakan bahwa FAE di beberapa produsen mikroprosesor utama masih menggunakan assembler, meskipun dengan cara yang berorientasi objek untuk penggunaan kembali kode yang sengaja.

Apa yang tidak saya lihat dalam jawaban yang disetujui adalah diskusi tentang tipe prosesor target dan / atau arsitektur yang diusulkan. Apakah ini pahit 0,50 $ 8 dengan memori terbatas? Apakah ini inti ARM9 dengan pipelining dan 8Meg flash? Coprocessor manajemen memori? Apakah akan memiliki OS? A while (1) loop? Perangkat konsumen dengan proses produksi awal 100000 unit? Perusahaan pemula dengan ide dan impian besar?

Walaupun saya setuju bahwa kompiler modern melakukan optimasi dengan baik, saya belum pernah mengerjakan proyek selama 30 tahun di mana saya tidak menghentikan debugger dan melihat kode assembly yang dihasilkan untuk melihat apa yang sedang terjadi di bawah kap ( memang merupakan mimpi buruk ketika pipelining dan optimisasi ikut bermain), jadi pengetahuan tentang perakitan itu penting.

Dan saya tidak pernah memiliki CEO, VP of Engineering, pelanggan yang tidak mendorong saya untuk mencoba dan memasukkan galon ke dalam wadah liter, atau menghemat $ 0,55 dengan menggunakan solusi perangkat lunak untuk memperbaiki masalah perangkat keras (hei itu hanya perangkat lunak benar? Whats sangat sulit?). Optimalisasi memori (kode atau data) akan selalu dihitung.

Maksud saya adalah jika Anda melihat proyek dari sudut pandang pemrograman murni Anda akan mendapatkan solusi lingkup yang lebih sempit. Mattnz sudah benar - membuatnya bekerja, kemudian membuatnya bekerja lebih cepat, lebih kecil, lebih baik, tetapi Anda masih perlu menghabiskan BANYAK waktu pada persyaratan dan hasil sebelum Anda bahkan berpikir tentang pengkodean.


Hai Gio, harap hindari HTML yang tidak perlu di pos Anda, dan gunakan sintaks penurunan harga . Untuk <br />Anda bisa tekan enter, dan untuk paragraf hanya meninggalkan garis kosong di antara mereka. Juga ketika Anda mereferensikan jawaban lain, silakan tambahkan tautan ke sana. Pada titik ini mungkin hanya ada beberapa jawaban tetapi mungkin ada lebih banyak, didistribusikan di banyak halaman, dan tidak akan terlalu jelas jawaban yang Anda maksud. Lihat riwayat revisi untuk melihat hasil edit saya.
yannis

@ Google Terima kasih telah menyebutkan faktor penting lainnya. +1 :)
AceofSpades

+1 - Perluasan jawaban saya.
mattnz

1

Manttz menjawab dengan sangat baik poin-poin kunci tentang bagaimana melakukan pemrograman "dekat dengan perangkat keras". Lagipula inilah yang dimaksudkan C.

Namun, saya ingin menambahkan bahwa sementara kata kunci ketat "Kelas" tidak ada di C - itu cukup mudah untuk berpikir dalam hal pemrograman berorientasi objek di C bahkan ketika Anda dekat dengan perangkat keras.

Anda dapat mempertimbangkan jawaban ini: OO praktik terbaik untuk program C yang menjelaskan hal ini.

Berikut adalah beberapa sumber yang akan membantu Anda menulis kode berorientasi objek yang baik dalam C.

Sebuah. Pemrograman berorientasi objek dalam C
b. ini adalah tempat yang baik di mana orang bertukar ide
c. dan inilah buku lengkapnya

Sumber bagus lain yang ingin saya sarankan kepada Anda adalah:

Seri Tulis Kode Hebat . Ini adalah dua buku volume. Buku pertama mencakup aspek-aspek yang sangat penting dari mesin di pekerjaan tingkat bawah. Buku kedua yang disentuh adalah "Berpikir tingkat rendah - menulis tingkat tinggi"


1

Anda memiliki beberapa masalah. pertama-tama Anda ingin proyek / kode ini portabel? Portabilitas membebani Anda dengan kinerja dan ukuran, dapatkah platform pilihan dan tugas yang Anda implementasikan menoleransi ukuran berlebih dan kinerja yang lebih rendah?

Ya, tentu saja pada mesin 8 bit yang mengembalikan karakter yang tidak ditandatangani alih-alih int atau celana yang tidak ditandatangani, adalah salah satu cara untuk meningkatkan kinerja dan ukuran. Demikian juga pada mesin 16 bit menggunakan celana pendek unsigned dan mesin 32 bit int unsigned. Anda dapat dengan mudah melihat bahwa jika Anda misalnya hanya menggunakan int unsigned di mana-mana untuk portabilitas di seluruh sistem yang mengambil alih (ARM misalnya mendorong jalan ke dalam daya terendah, pasar perangkat terkecil) kode itu adalah perangkat rom besar di mikro 8 bit. Anda tentu saja bisa menggunakan unsigned tanpa int atau short atau char dan biarkan kompiler memilih ukuran optimal.

Tidak hanya perakitan inline, tetapi bahasa assembly secara umum. Perakitan inline sangat non-portabel dan lebih sulit untuk ditulis dengan baik daripada hanya memanggil fungsi asm. ya Anda membakar pengaturan panggilan dan kembali tetapi dengan biaya pengembangan yang lebih mudah, pemeliharaan yang lebih baik, dan kontrol. Aturan masih berlaku, hanya tulislah asm jika Anda benar-benar perlu, sudahkah Anda melakukan pekerjaan untuk menyimpulkan bahwa output kompiler adalah masalah Anda di bidang ini dan berapa banyak keuntungan kinerja yang bisa Anda dapatkan dengan melakukannya dengan tangan. Kemudian kembali ke portabilitas dan pemeliharaan, segera setelah Anda mulai mencampur C dan ASM, dan setiap kali Anda mencampur C dan ASM Anda mungkin membahayakan portabilitas Anda, dan mungkin membuat proyek kurang dapat dipelihara tergantung pada siapa lagi yang mengerjakannya atau jika ini adalah produk yang sedang Anda kembangkan sekarang dan orang lain harus mempertahankannya. Setelah Anda melakukan analisis itu, Anda secara otomatis tahu apakah Anda harus pergi inline atau pergi dengan perakitan lurus. Saya memiliki 25+ tahun di lapangan, menulis campuran C dan asm setiap hari, hidup di / pada lapisan perangkat keras / lunak dan, yah, tidak pernah menggunakan asm inline. Ini jarang sepadan dengan usaha, terlalu spesifik kompiler, saya menulis kode non-spesifik kompilator sedapat mungkin (hampir di mana-mana).

Kunci untuk seluruh pertanyaan Anda adalah membongkar kode C. Pelajari apa yang dilakukan kompiler dengan kode Anda, dan seiring waktu, jika Anda menginginkannya, Anda dapat belajar memanipulasi kompiler untuk menghasilkan kode yang Anda inginkan tanpa harus menggunakan asm sebanyak mungkin. Dengan lebih banyak waktu Anda dapat belajar memanipulasi kompiler untuk menghasilkan kode yang efisien di berbagai target sehingga kode lebih portabel tanpa harus menggunakan asm. Anda seharusnya tidak memiliki masalah untuk melihat mengapa char yang tidak ditandatangani berfungsi lebih baik sebagai status yang kembali dari suatu fungsi daripada yang tidak ditandatangani pada mikro 8-bit, demikian juga char yang tidak ditandatangani menjadi lebih mahal pada sistem 16 dan 32 bit (beberapa arsitektur membantu Anda keluar, sebagian tidak).

Beberapa mikrokontroler 8 bit, semua ?, sangat kompiler tidak ramah dan tidak ada kompiler yang menghasilkan kode yang baik. Tidak ada permintaan yang cukup untuk menciptakan pasar kompiler untuk perangkat tersebut untuk membuat kompiler yang bagus untuk target tersebut sehingga kompiler yang ada di sana untuk menarik lebih banyak bisnis, programmer non-asm, dan bukan karena kompiler lebih baik daripada tulisan tangan . lengan dan mips masuk ke dunia ini mengubah model itu karena Anda memiliki target yang memang memiliki kompiler yang telah memiliki banyak pekerjaan yang dilakukan pada mereka, kompiler yang menghasilkan kode yang cukup bagus, dll. Untuk mikros dengan prosesor seperti itu Anda tentu masih memiliki kasus di mana Anda harus drop down ke asm, tetapi tidak sering, itu jauh lebih mudah untuk hanya memberitahu kompiler apa yang Anda inginkan daripada tidak menggunakannya. Perhatikan bahwa memanipulasi kompiler bukanlah kode yang jelek dan tidak dapat dibaca, sebenarnya itu kebalikannya, bagus bersih, kode mudah, mungkin mengatur ulang beberapa item. Mengontrol ukuran fungsi Anda dan jumlah parameter, hal semacam itu membuat perbedaan besar dalam output kompiler. Hindari fitur ghee-jagoan dari kompiler atau bahasa, KISS, tetap sederhana, sering menghasilkan kode yang jauh lebih baik dan lebih cepat.


Anda tidak menyatakan jenis produk yang Anda hasilkan, saya akan berasumsi itu baik volume yang sangat tinggi, margin rendah atau ceruk pasar tertentu dengan margin gila. Ini sangat penting untuk memutuskan pada tingkat bisnis jika Anda harus menggunakan assembler mikro 8 bit kecil dan kerajinan tangan, atau mikro dan C. yang lebih besar. Sebagai tanggapan atas komentar Anda (dihapus?) - Saya bekerja dengan mikro 8 bit, namun kami mulai dengan mikro yang lebih besar dari yang dibutuhkan dan revisi turun hanya ketika dan jika biaya BOM menjadi masalah) Waktu ke pasar, biaya opertunity dan biaya pengembangan diamortisasi memungkinkan kita kemewahan menambahkan 10 atau 20 sen ke BOM.
mattnz
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.