Mikrodenetleyiciler için Verimli C Kodu Yazma Kaynakları? [kapalı]


15

Burada ciddi yardıma ihtiyaç vardı. Programlamayı seviyorum. Son zamanlarda bir grup kitap (K&R gibi) ve C dili için çevrimiçi makaleler / forumlar okuyorum. Hatta Linux koduna bakmayı denedim (nereden başlayacağımı kaybettim ama küçük kütüphanelere bakmak yardımcı oldu mu?).

Bir Java programcısı olarak başladım ve Java'da oldukça kesilmiş ve kuru; Programlar çok büyürse, sınıflarda dilimleyin, sonra işlevlere bölün. Gibi yönergeler, kodu okunabilir tutun ve yorum ekleyin. Bilgi gizleme ve OOP tekniklerini kullanır. Bazıları hala C için geçerlidir.

Ben şimdi C kodlama ve şimdiye kadar şu ya da bu şekilde çalışmak programları olsun. Birçok kişi performans / verimlilik, algoritma / tasarım, optimizasyon ve sürdürülebilirlik hakkında konuşur. Bazı insanlar diğerinden daha fazla vurgu yaparlar ancak profesyonel olmayan yazılım mühendisleri için sık sık şöyle bir şey duyarsınız: Linux kernel dev sadece kod almaz.

Sorum şu: 8-bit mikrodenetleyici için herhangi bir kaynak israf etmeden kod yazmayı planlıyorum . Java arka plandan geliyorum biliyorum, bu yüzden işler artık aynı değil ... kaynaklar / kitaplar / linkler / ipuçları çok takdir edilecektir. Performans ve boyut artık önemlidir. 8 bitlik mikro kontrolörler için verimli (en iyi uygulamalar dahilinde) C kodu üzerindeki Kaynaklar / Püf Noktaları?

Ayrıca, inline assemblymikro kontrolör standardına yakın yapışmanın yanı sıra hayati bir rol oynar. Ancak verimlilik için herkes için geçerli olan genel kural var mı?

Örneğin: her zaman register unsigned int variable_name;tercih edilir char. Veya uint8_t büyük sayılara ihtiyacınız yoksa kullanmak .

EDIT: Tüm cevap ve önerileriniz için çok teşekkür ederim. Herkesin bilgiyi paylaşma çabasını takdir ediyorum.


2
Bu genellikle bir x86 işlemci için geçerli değildir, ancak bir mikro denetleyicide, her son performans düşüşünü elde ettiğinizden emin olmak istiyorsanız, muhtemelen montajı kullanmak isteyeceksiniz.
Rei Miyasaka

3
@Rei: El yapımı Montaj nadiren, eğer varsa, daha az bellek kullanır ve modern C derleyicilerinden daha hızlıdır. C'de yapılabildiği zaman (gerektiği gibi) montajı kodlamak zaman kaybıdır
mattnz

1
@mattnz Modernden ne kadar yeni bahsediyorsun? Dürüst olmak gerekirse, yaklaşık on yıldır mikrodenetleyici için kod yazmadım.
Rei Miyasaka

2
Basit bir ipucu: mikronkontrollerde genellikle "daha basitse daha hızlı" olduğu doğrudur. Karmaşık yongalarda (ARM ve yukarı) donanım, test edene kadar asla bilemeyeceğiniz kadar optimizasyon yapar.
Javier

1
@ Bakım maliyetinde büyük bir artış ile ReiMiyasaka. İyi bir C derleyicisi, oldukça deneyimli bir programcıyla hemen hemen aynı kodu üretebilir.

Yanıtlar:


33

20 yıldan fazla gömülü sistemim var, çoğunlukla 8 ve 16 mikro. Sorunuzun kısa cevabı diğer yazılım geliştirmeleriyle aynıdır - ihtiyacınız olduğunu bilinceye kadar optimizasyon yapmayın ve neyi optimize etmeniz gerektiğini bilinceye kadar optimizasyon yapmayın. Önce güvenilir, okunabilir ve bakımı kolay olacak şekilde kod yazın. Erken optimizasyon, gömülü sistemlerde daha fazla olmasa da bir sorundur

"Kaynak israf etmeden" programladığınızda zamanınızı bir kaynak olarak mı değerlendiriyorsunuz? Değilse, zamanınız için size kim ödeme yapıyor ve kimse yoksa, bununla daha iyi bir şeyleriniz var mı? Seçim bir kez herhangi bir gömülü sistem tasarımcısı yapmak zorunda donanım maliyeti vs mühendislik zaman maliyeti. 100 birim gönderiyorsanız, 100.000 birimde daha büyük bir mikro kullanın, birim başına 1,00 ABD doları tasarruf, 1 milyon yıllık yazılım geliştirme (piyasaya çıkış süresini, fırsat maliyetini vb. Göz ardı ederek) ile aynıdır, 1 Milyon birimde, kaynak kullanımı konusunda takıntılı olduğu için yatırım getirisi elde etmek, ancak dikkatli olun çünkü birçok gömülü proje 1 milyon puan vermedi çünkü 1 milyon (düşük üretim maliyetiyle yüksek ilk yatırım) satmak için tasarlandı ve oraya varmadan büstü gitti.

Bununla birlikte, (küçük) gömülü sistemlerle ilgili düşünmeniz ve farkında olmanız gereken şeyler, çünkü bunlar onu yavaşlatmakla kalmayıp, beklenmedik şekillerde çalışmasını durduracaktır.

a) Yığın - genellikle sadece küçük bir yığın boyutuna ve genellikle sınırlı yığın çerçeve boyutlarına sahipsiniz. Yığın kullanımınızın her zaman ne olduğunun farkında olmalısınız. Dikkat edin, yığın sorunları en sinsi kusurların bazılarına neden olur.

b) Yığın - yine, küçük yığın boyutları bu yüzden haksız bellek ayırma konusunda dikkatli olun. Parçalanma bir sorun haline gelir. Bu iki ile, bittiğinde ne yaptığınızı bilmeniz gerekir - OS tarafından sağlanan disk belleği nedeniyle büyük bir sistemde olmaz. yani malloc NULL döndürdüğünde, onu ve ne yaptığınızı kontrol edersiniz. Her ebegümeci bir kontrol ve işleyici, kod şişkinlik gerekir ?. Bir rehber olarak - bir alternatif varsa kullanmayın. Çoğu küçük sistem bu nedenlerden dolayı dinamik bellek kullanmaz.

c) Donanım kesintileri - Bunların güvenli ve zamanında nasıl ele alınacağını bilmeniz gerekir. Ayrıca güvenli yeniden giriş kodunun nasıl oluşturulacağını da bilmeniz gerekir. Örneğin, C standart kütleleri genellikle yeniden giriş yapmazlar, bu nedenle kesme işleyicileri içinde kullanılmamalıdır.

d) Montaj - neredeyse her zaman erken optimizasyon. C'nin yapamayacağı bir şeyi başarmak için en az küçük bir miktar (satır içi) gereklidir. Bir egzersiz olarak, el yapımı montajda küçük bir yöntem yazın (sıfırdan). Aynı işlemi C'de yapın. Performansı ölçün. Bahse girerim C daha hızlı olur, daha okunabilir, bakımı ve genişletilebilir olacağını biliyorum. Şimdi egzersizin 2. bölümü için - montaj ve C'de yararlı bir program yazın
.

Bunu nasıl yapacağınızı bilmeye değer, hatta bir veya iki ortak mikron için dillerde yetkin olmaya değer olabilir.

e) "imzasız int değişken_adı kaydet", "register" her zaman 70'lerin başında (40 yıl önce) derleyici için bir talimat değil, bir ipucu olmuştur. 2012'de, derleyiciler çok akıllı olduğu ve tuş takımlarının çok karmaşık olduğu için tuş vuruşları israfı.

Linux yorumunuza geri dönün - burada yaşadığınız sorun, sadece 1 milyon üniteden bahsetmiyoruz, 100 milyondan bahsediyoruz, sonsuza kadar yaşam süresiyle. İnsanca mümkün olduğunca optimum hale getirmenin mühendislik süresi ve maliyeti, buna değer. Her ne kadar en iyi mühendislik uygulamasına iyi bir örnek olsa da, çoğu gömülü sistem geliştiricisinin linux çekirdeğinin gerektirdiği kadar bilgiç olmaları ticari bir intihar olacaktır.


4
mattnz: Bu .stackexchange sitelerinde en güzel cevaplardan biridir.
Ahmed Masud

1
Bu cevabı geliştiremem. Sadece montaj kodu eklemenin nadiren performans için mantıklı olduğunu ekleyebilirim, ancak G / Ç çiplerini veya C'de yapılması kolay olmayan diğer donanım numaralarını
dürtmek

@mattnz İyi yanıtladığınız için teşekkürler. +1
AceofSpades

1
@MikeDunlavey birleştirici bazen tam zamanlama için gereklidir. Bir G / Ç piminde NTSC video oluşturmak için bit beceriyor kullanan bir video yer paylaşımını bitirdim, zamanlama - 3clock döngüleri için voltaj yüksek, sonra 6 için düşük ....
Martin Beckett

@ Martin: Bu çok mantıklı. Bu seviyede kodladığımdan bu yana uzun zaman geçti.
Mike Dunlavey

3

Sorunuz ("kaynakları boşa harcamadan") çok genel, bu yüzden çok tavsiye vermek zor. Kelimenin tam anlamıyla ele alındığında, kaynakları boşa harcamak istemiyorsanız, belki bir adım geriye gitmeli ve herhangi bir şey yapmanız gerekip gerekmediğini, yani sorunu başka şekillerde çözüp çözemeyeceğinizi değerlendirmelisiniz.

Ayrıca, yararlı tavsiyeler kısıtlamalarınıza çok bağlıdır - ne tür bir sistem kuruyorsunuz ve ne tür bir CPU kullanıyorsunuz? Zor bir gerçek zamanlı sistem mi? Kod ve veriler için ne kadar belleğiniz var? Doğal olarak tüm C işlemlerini (özellikle çarpma ve bölme) ve hangi tipler için destekliyor? Daha genel olarak: tüm veri sayfasını okuyun ve anlayın .

En önemli tavsiye: basit tutun.

Örneğin: karmaşık veri yapılarını (karmalar, ağaçlar, hatta bağlantılı listeler) unutun ve sabit boyutlu diziler kullanın. Daha karmaşık veri yapılarının kullanımı, ancak dizilerin çok yavaş olduğunu ölçtüğünüz kanıtlandıktan sonra garanti edilir.

Ayrıca, aşırı tasarım yapmayın (Java / C # devs'in bir şey yapma eğilimi vardır): çok fazla katman oluşturmadan basit prosedür kodu yazın. Soyutlamanın bir maliyeti var!

Küresel değişkenleri kullanma ve goto [istisnaların yokluğunda temizlik için çok yararlı];

Kesintilerle uğraşmak zorunda kalırsanız, yeniden giriş hakkında okuyun. Evresel kod yazmak önemsizdir.


3

Mattnz'nin cevabına katılıyorum - çoğunlukla. 30 yıl önce 8085'te programlamaya başladım, sonra Z80, sonra hızla 8031'e geçtim. Daha sonra 68300 serisi mikrodenetleyicilere, sonra 80x86, XScale, MXL ve (geç itibariyle) 8 bitlik PICS'ye gittim. sanırım tam bir daire çizdim. Kayıt için, birkaç büyük mikroişlemci üreticisinde bulunan FAE'lerin, amaçlı kodların yeniden kullanılması için nesne yönelimli olsa da, hala montajcı kullandığını söyleyebilirim.

Onaylanan cevapta görmediğim şey, hedef işlemci tipi ve / veya önerilen mimarinin tartışması. Sınırlı hafızaya sahip bir 0,50 $ 8 acı mı? Boru hattı ve 8Meg flaşlı bir ARM9 çekirdeği mi? Bellek yönetimi yardımcı işlemcisi? İşletim sistemi olacak mı? Bir süre (1) döngü? 100.000 adet üretim aşamasına sahip bir tüketici cihazı mı? Büyük fikirleri ve hayalleri olan bir başlangıç ​​şirketi mi?

Modern derleyicilerin mükemmel bir optimizasyon işi yaptığını kabul etsem de, 30 yıldır hiç bir projede çalışmadım, burada hata ayıklayıcıyı durdurmadım ve sadece başlık altında neler olup bittiğini görmek için oluşturulan montaj kodunu görüntüledim ( Kuşkusuz boru hattı ve optimizasyon devreye girdiğinde bir kabus), bu yüzden montaj bilgisi önemlidir.

Ve asla CEO'yu, Mühendislik Başkan Yardımcısı, beni dörtte bir konteynere bir galon doldurmaya zorlamayan veya bir donanım sorununu çözmek için bir yazılım çözümü kullanarak .05 $ tasarruf etmeyen müşteri (hey sadece yazılım Çok zor olan ne?). Bellek (kod veya veri) optimizasyonu her zaman dikkate alınacaktır.

Demek istediğim, projeyi saf bir programlama bakış açısıyla izlerseniz, daha dar bir kapsam çözümü akıllıca elde edersiniz. Mattnz bunu haklı çıkar - çalışmasını sağlayın, daha hızlı, daha küçük, daha iyi çalışmasını sağlayın, ancak yine de kodlamayı düşünmeden önce gereksinimler ve çıktılar üzerinde çok fazla zaman harcamanız gerekir.


Merhaba Gio, lütfen yazılarınızda gereksiz HTML kullanmaktan kaçının ve bunun yerine İşaretleme sözdizimini kullanın. Çünkü <br />enter tuşuna basabilirsiniz ve paragraflar arasında aralarında boş bir satır bırakın. Ayrıca başka bir cevaba referans verirken, lütfen cevabın bağlantısını ekleyin. Bu noktada sadece birkaç cevap olabilir, ancak birçok sayfaya dağıtılmış daha fazla olabilir ve hangi cevabı kastettiğiniz çok açık olmayacaktır. Düzenlemelerimi görmek için düzeltme geçmişine göz atın .
yannis

@Gio Diğer önemli faktörlerden bahsettiğiniz için teşekkür ederiz. +1 :)
AceofSpades

+1 - Cevabımın güzel bir şekilde genişlemesi.
mattnz

1

Manttz cevabı, "donanıma yakın" programlamanın nasıl yapılacağı ile ilgili en önemli noktaları çok iyi bir şekilde ortaya koyuyor. Ne de olsa C'nin amacı budur.

Ancak, "Sınıf" katı anahtar kelime C bulunmazken eklemek istiyorum - donanım yakın olduğunda bile C nesne odaklı programlama açısından düşünmek oldukça basittir .

Şu yanıtı düşünebilirsiniz: Bu programı açıklayan C programları için OO en iyi uygulamaları .

C'de iyi nesne yönelimli kod yazmanıza yardımcı olacak bazı kaynaklar.

a. C dilinde nesne yönelimli programlama
b. burası insanların fikir alışverişinde bulunduğu iyi bir yerdir
c. ve işte tam kitap

Size önermek istediğim bir başka iyi kaynak:

Büyük Kod Yazma Serisi . Bu iki ciltli kitap. İlk kitap, daha düşük seviyeli işlerde makinelerin çok önemli yönlerini kapsamaktadır. İkinci kitap, "Düşük Seviyede Düşünmek - Yüksek Seviyede Yazmak"


1

Birkaç sorununuz var. önce bu projenin / kodun taşınabilir olmasını ister misiniz? Taşınabilirlik size performans ve boyut maliyeti, uyguladığınız seçim ve görev platformunuz aşırı boyutu ve daha düşük performansı tolere edebilir mi?

Evet, kesinlikle imzasız ints veya şort yerine imzasız karakter döndüren 8 bitlik bir makinede, performansı ve boyutu artırmanın bir yoludur. Aynı şekilde 16 bit makinede imzasız şort ve 32 bit makinede imzasız ints kullanın. Örneğin, devralınan sistem boyunca taşınabilirlik için her yerde imzasız ints kullandıysanız (ARM, örneğin en düşük güç, en küçük cihaz pazarlarına doğru ilerlerken) bu kodun büyük bir rom domuzu olduğunu kolayca görebilirsiniz. 8 bit mikro. Tabii ki int veya short veya char olmadan imzasız kullanabilirsiniz ve derleyicinin en uygun boyutu seçmesine izin verebilirsiniz.

Sadece satır içi montaj değil, genel olarak montaj dili. Satır içi montaj çok taşınabilir değildir ve sadece bir asm işlevi çağırmaktan daha iyi yazmak zordur. evet çağrı kurulum ve dönüş yakmak ama daha kolay geliştirme, daha iyi bakım ve kontrol pahasına. Kural hala geçerlidir, sadece gerçekten ihtiyacınız varsa asm'de yazın, derleyici çıktısının bu alandaki sorununuz olduğunu ve bunu elle gerçekleştirerek ne kadar bir performans kazancı elde edebileceğinizi sonuçlandırmak için işi yaptınız mı? Ardından, C ve asm'i karıştırmaya başlar başlamaz, taşınabilirliğe ve bakıma geri dönün ve C ile her karıştırdığınızda taşınabilirliğinize zarar verebilirsiniz ve üzerinde başka kimin çalıştığına veya şu anda geliştirdiğiniz bir üründür ve bir başkası yolda kalmalıdır. Bu analizi yaptıktan sonra, satır içi veya düz montaj ile gitmek zorunda olup olmadığınızı otomatik olarak bilirsiniz. Sahada 25 yılı aşkın bir sürem var, her gün C ve asm karışımları yazıyorum, donanım / yazılım katmanında / üzerinde yaşıyorum ve aslında satır içi asm kullanmıyorum. Nadiren çabaya değer, çok derleyiciye özel, mümkün olan her yerde derleyici spesifik olmayan kod yazıyorum (neredeyse her yerde).

Tüm sorunuzun anahtarı C kodunuzu sökmektir. Derleyicinin kodunuzla ne yaptığını öğrenin ve zamanla, eğer isterseniz, derleyiciyi istediğiniz kadar kod oluşturmaya gerek kalmadan istediğiniz kodu üretmeye yönlendirmeyi öğrenebilirsiniz. Daha fazla zamanla, derleyiciyi birden fazla hedefte verimli kod üretmek için manipüle etmeyi öğrenerek kodu asm yapmak zorunda kalmadan daha taşınabilir hale getirebilirsiniz. İmzasız karakterin neden işlevden geri döndüğünü 8 bitlik bir mikroda imzasızdan daha iyi çalıştığını görmekte sorun yaşamamalısınız, aynı şekilde imzasız karakterin 16 ve 32 bit sistemlerde daha pahalı olması gerekir (bazı mimariler size yardımcı olur) dışarı, bazıları yok).

Bazı 8 bit mikrodenetleyiciler, hepsi ?, çok derleyici düşmanca ve hiçbir derleyici iyi kod üretmez. Bu cihazların bu hedefler için harika bir derleyici oluşturması için bir derleyici pazarı oluşturmak için yeterli talep yoktur, bu yüzden orada bulunan derleyiciler daha fazla iş, asm olmayan programcı çekmek için vardır ve derleyici elle yazılmış asmdan daha iyi olduğu için değil . Bu dünyaya giren kol ve mipsler, üzerinde çok fazla iş yapmış derleyicilere, oldukça iyi kod üreten derleyicilere vb. sahip hedeflere sahip olduğunuz için bu modeli değiştiriyor. Tabii ki böyle işlemcilere sahip mikrolar için asm'a bırakmanız gereken durumda, ancak çoğu zaman değil, derleyiciye ne yapmasını istediğinizi söylemekten çok daha kolay. Bir derleyiciyi değiştirmenin çirkin, okunamayan bir kod olmadığını unutmayın, Aslında, belki de birkaç öğeyi yeniden düzenlemek, tam tersi, güzel temiz, açık kod. Fonksiyonlarınızın boyutunu ve parametre sayısını kontrol ederek, bu tür şeyler derleyici çıktısında büyük bir fark yaratır. Derleyicinin veya dilin ghee-whiz özelliklerinden kaçının, KISS, basit aptal tutun, genellikle çok daha iyi ve daha hızlı kod üretir.


Ürettiğiniz ürünlerin türünü belirtmezsiniz, çok yüksek hacimli, düşük marjlı veya deli marjlı özel niş pazar olduğunu varsayarım. Bu, küçük bir 8 bit mikro ve el yapımı montajcı veya daha büyük bir mikro ve C kullanmanız gerekiyorsa, işletme düzeyinde karar vermek için kritiktir (silinen?) Yorumunuza yanıt olarak - 8 bit mikrolarla çalışıyorum, ancak biz ihtiyaç duyulandan daha büyük bir mikro ile başlayın ve sadece ürün ağacı maliyeti bir sorun haline geldiğinde gözden geçirin) Piyasaya çıkış süresi, fırsat maliyeti ve amortismana tabi tutulmuş geliştirme maliyeti ürün ağacına 10 veya 20 sent ekleme lüksüne izin verir.
mattnz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.