Misc

Optimizarea codului în microcontrolere

Autor: Laura McKinney
Data Creației: 4 Aprilie 2021
Data Actualizării: 16 Mai 2024
Anonim
Optimizing C for Microcontrollers - Best Practices - Khem Raj, Comcast RDK
Video: Optimizing C for Microcontrollers - Best Practices - Khem Raj, Comcast RDK

Conţinut

Autorul și-a finalizat proiectul de inginerie din ultimul an cu microcontrolerele dsPic, obținând o perspectivă extinsă asupra acestor dispozitive.

Codul de limbă C al unui microcontroler poate necesita optimizare în anumite aplicații avansate. Această optimizare a codului se practică pentru a reduce două lucruri cruciale:

  1. Dimensiune cod: Microcontrolerele pot stoca date și instrucțiuni limitate din cauza dimensiunii limitate a memoriei RAM. Prin urmare, codul trebuie optimizat, astfel încât instrucțiunile disponibile și memoria de date să poată fi utilizate în cel mai eficient mod.
  2. Timpi de executare a codului: Microcontrolerele sunt dispozitive secvențiale care execută o instrucțiune la un moment dat. Fiecare instrucțiune de asamblare consumă un anumit număr de cicluri de ceas pentru a se executa singură. Prin urmare, codul trebuie optimizat pentru a se asigura că îndeplinește sarcina necesară în cel mai mic număr de cicluri de ceas sau instrucțiuni de asamblare. Cu cât un cod folosește mai puține cicluri, cu atât rulează mai repede. Aceasta înseamnă că aplicațiile pot rula mai repede, deoarece timpul de procesare este minimizat.

Acest articol prezintă sfaturi și trucuri care pot fi folosite pentru a reduce dimensiunea și timpul de execuție al unui cod de microcontroler.


IDE-ul de dezvoltare MplabX al Microchip va fi folosit pentru a demonstra exemple acolo unde este cazul.

Cum se măsoară experimental timpul de executare a codului

Pentru a vă face o idee despre cât timp necesită codul dvs. pentru a se executa în timp real, trebuie să îl măsurați experimental. Un analizor logic poate fi utilizat în mod convenabil pentru a măsura timpul de execuție a codului și cei interesați pot întreba despre acest proces de la mine prin e-mail. Pe lângă asta:

  • Unele compilatoare au capacitatea de a număra ciclurile de ceas pe care le va consuma un cod.
  • Unele depanatoare, de exemplu ICD 3 din microcip, pot măsura direct timpul de execuție printr-un cronometru.

1. Cunoașteți puterea de procesare și dimensiunea memoriei microcontrolerului

Nu întotdeauna frecvența ceasului (Mhz) oferă imaginea reală a vitezei de procesare a unui microcontroler, o măsură mai realistă este MIPS (mega instrucțiuni pe secundă) sau numărul de instrucțiuni pe care MCU le poate executa într-o secundă.

MCU-urile variază de obicei de la 60-70 MIPS în categoria high-end la 20 MIPS 8-bit AVR-uri. Este probabil ca un microcontroler MIPS să fie mai scump decât un dispozitiv low-end, așa că aici aveți un compromis între cost și viteza de procesare.


Microcontrolerele au memorie separată pentru stocarea datelor și a codului de program. Dimensiunea ambelor poate fi găsită din foaia de date. Este posibil să aveți nevoie de un MCU cu o dimensiune de memorie mai mare dacă codul dvs. este substanțial mare.

2. Alegerea variabilelor pentru optimizare în dimensiunea codului

Microcontrolerele au o memorie de date limitată, de obicei cuprinsă între 1 și 4 Kbyte. În acest caz, este înțelept să alegeți cel mai potrivit tip de variabilă în funcție de intervalul așteptat al datei stocate. Tabelul de mai jos rezumă aceste variabile:

Rezumatul variabilelor utilizate în limbajul C.

Tip variabilDimensiune în octețiGamă

bool

1

Numai 0 sau 1

char

1


-128 până la 127

int

2

-32.768 până la 32.767

nesemnat int

2

De la 0 la 65.535

lung

4

-2.147.483.648 până la 2.147.483.647

pluti

4

Precizați până la 6 zecimale

dubla

8

Precizați până la 15 zecimale

lung dublu

10

Precizați până la 19 zecimale

Exemplu:

  • Dacă se adaugă două variabile X și Y, iar rezultatul trebuie stocat în Z, dar valoarea lui Z este de așteptat să fie mai mare decât 65.535 după adăugare, atunci Z poate fi declarat ca lung și X și Y pot fi declarate ca nesemnate int, valorile lui X și Y nu sunt, de asemenea, de așteptat să devină negative. Acest lucru va salva 04 octeți în memoria de date care altfel ar fi fost epuizate dacă toate variabilele ar fi declarate atât de mult.
  • Se vor împărți două variabile X și Y, ale căror valori se așteaptă să fie în număr întreg, dar rezultatul divizării poate produce o zecimală, apoi X și Y pot fi declarate int și rezultatul poate fi declarat float sau dublu în funcție de precizia necesară.

Alegerea tipului de date poate fi crucială atunci când se declară matrice care conțin un număr mare de elemente.

3. Alegerea variabilelor pentru optimizare în timpul executării codului

  • Este un fapt stabilit că calculele în virgulă mobilă durează mai mult decât calculele în virgulă fixă. Nu utilizați o variabilă în virgulă mobilă în cazul în care nu este necesară o valoare zecimală. Lucrați cu numere întregi nesemnate ori de câte ori este posibil.
  • Variabilele locale sunt preferate variabilelor globale. Dacă o variabilă este utilizată doar într-o funcție, atunci aceasta trebuie declarată în acea funcție, deoarece accesarea variabilelor globale este mai lentă decât variabilele locale.
  • Un MCU pe 8 biți va găsi o variabilă cu un singur octet mai rapid de accesat, iar un MCU pe 16 biți va găsi o variabilă de 2 octeți mai ușor de accesat datorită lungimii adresei generate.

4. Optimizarea operațiunilor aritmetice

Operațiile aritmetice pot fi optimizate în următoarele moduri.

  1. Utilizați tabele de căutare cu valori precalculate în loc să evaluați un Sine sau orice altă funcție trigonometrică sau orice altă operațiune al cărei rezultat poate fi cunoscut în prealabil în cod.
  2. În cazul în care un tabel de căutare sinusoidală este deja stocat în memorie, un cosinus poate fi evaluat prin avansarea indicatorului matrice echivalent la 90 de grade.
  3. Dintre cele patru operații aritmetice, împărțirea și înmulțirea necesită cel mai mult timp de procesare, în practică poate fi în intervalul a sute de micro-secunde sau cam așa în cazul valorilor în virgulă mobilă.
  4. Folosiți instrucțiuni de schimbare a biților în loc de divizare și multiplicare. O instrucțiune de schimbare dreaptă 3 servește la împărțirea la 23 unde ca instrucțiune de schimbare la stânga 1 va servi să se înmulțească cu 21.

5. Utilizați un microcontroler capabil DSP pentru calcule intensive

Unele microcontrolere au o unitate de procesare DSP, alta decât ALU convențional, încorporată în arhitectura lor. Acest motor DSP este conceput pentru a efectua calcule aritmetice foarte rapid în cel mai mic număr de cicluri de ceas (unul în cele mai multe cazuri) de multe ori mai rapid decât ALU.

Instrucțiunile pe care un procesor DSP le poate efectua mai repede decât un ALU sunt:

  • Instrucțiuni de schimbare și rotire a biților.
  • Înmulțiri, diviziuni și alte operații aritmetice.
  • Evaluarea sinusurilor și a altor funcții trigonometrice.
  • Toate operațiile DSP, cum ar fi FFT, DFT, convoluție și filtrare FIR.

Utilizarea motorului DSP al unui microcontroler necesită:

  • Bibliotecile DSP separate sunt încorporate în proiect.
  • Numele funcțiilor sunt diferite de biblioteca matematică standard a limbajului C. Documentarea acestor biblioteci și funcții poate fi accesată de pe site-ul web al producătorilor respectivi.
  • Motorul DSP utilizează un alt tip de variabil „fracțional”. Aflați cum să utilizați variabile de tip fracțional înainte de a continua cu funcțiile bibliotecii dsp.

Rețineți că funcțiile standard de bibliotecă matematică nu vor invoca motorul DSP deoarece sunt traduse în instrucțiuni de asamblare ALU.

6. Lucrați cu întreruperi

Utilizați întreruperi pentru îndeplinirea funcțiilor specifice, cum ar fi:

  • Citirea valorilor ADC.
  • Trimiterea și primirea de la UART.
  • Actualizarea registrelor ciclului de funcționare PWM.
  • Comunicare CAN sau I2C.

Întreruperile vor deservi aceste funcții rapid în comparație cu efectuarea lor în corpul principal prin intermediul unui apel de funcție sau a unui cod inline.

Întreruperile vor declanșa, de asemenea, numai atunci când este necesar, în timp ce, dacă este codat în corpul principal, codul se va executa în fiecare iterație a buclei while (1).

7. Utilizați cele mai bune compilatoare disponibile

Compilatoarele pot implementa automat unele dintre optimizările discutate mai sus în timp ce traduc codul din limbajul C în limbajul de asamblare dacă sunt configurate corect. Căutați opțiuni de optimizare în compilatorul dvs. și, dacă este posibil, faceți upgrade la versiunile profesionale ale compilatoarelor, deoarece acestea sunt optimizatoare de cod mai puternice.

8. Folosiți afirmațiile condiționate în mod inteligent

  • Când utilizați o serie de afirmații if-else păstrați cea mai probabilă condiție mai întâi. În acest fel, MCU nu va trebui să scaneze toate condițiile după ce va găsi adevărata condiție.
  • O instrucțiune switch-case este de obicei mai rapidă decât if-else.
  • Utilizați instrucțiuni imbricate if-else în locul unei serii de enunțuri. Un bloc if-else cu mai multe instrucțiuni poate fi împărțit în subramuri mai mici pentru a optimiza pentru cel mai rău caz (ultima) stare.

9. Utilizați funcțiile Inline

Funcțiile care urmează să fie utilizate o singură dată în cod pot fi declarate ca fiind statice. Acest lucru va face ca compilatorul să optimizeze acea funcție într-o funcție inline și, prin urmare, nu va fi tradus niciun cod de asamblare pentru apelul de funcție.

  • O funcție poate fi declarată în linie utilizând cuvântul cheie „static” împreună cu aceasta.

10. Utilizați bucle decrementate

O buclă decrementată va genera mai puțin cod de asamblare în comparație cu o buclă incrementată.

Asta pentru că într-o buclă incrementală, este necesară o instrucțiune de comparație pentru a compara indicele buclei cu valoarea maximă din fiecare buclă pentru a verifica dacă indicele buclei atinge valoarea maximă. Dimpotrivă, într-o buclă de decrementare, această comparație nu mai este necesară, deoarece rezultatul decrementat al indicelui de buclă va seta steagul zero în SREG dacă atinge zero.

Având în vedere că bucla trebuie să itereze de sute de ori, reducerea unei instrucțiuni din buclă va evita executarea ei de o sută de ori, astfel încât impactul este probabil mai semnificativ atunci când bucla trebuie să itereze de mai multe ori.

Încheierea

Aceste sfaturi pot fi utile, dar adevărata lor aplicație și potențial depinde de abilitatea programatorului și de comanda pe care o are asupra codului său. Amintiți-vă, dimensiunea programului nu determină întotdeauna timpii de execuție, unele instrucțiuni pot consuma mai multe cicluri de ceas, apoi celelalte, astfel încât, din nou, abilitățile programului trebuie să joace rolul lor.

Acest articol este corect și fidel, după cunoștințele autorului. Conținutul are doar scop informativ sau de divertisment și nu înlocuiește consilierea personală sau sfatul profesional în probleme de afaceri, financiare, juridice sau tehnice.

Publicațiile Noastre

Noi Publicații

Cum să vă protejați telefonul sau tableta împotriva pirateriei cu sucuri
Telefoane

Cum să vă protejați telefonul sau tableta împotriva pirateriei cu sucuri

Un I.T. Profe ioni t cu pe te 15 ani în indu trie. Un profe ioni t certificat Micro oft, admini trator de i teme certificat Micro oft.Nu ați auzit niciodată de termenul de uc de bătaie? Ei bine, ...
Cum să faci GIF-uri din videoclipuri și fotografii
Calculatoare

Cum să faci GIF-uri din videoclipuri și fotografii

Am creat un program care face GIF-uri animate din fotografii și videoclipuri. Apoi l-am folo it pentru a face animații 3D.Fotografiile JPG și PNG mici pot conține mii de culori unice. GIF-urile accept...