Näytä sivun lähdekoodiVanhat versiotPaluulinkitTakaisin ylös Millainen on hyvä sulautetun C-koodi? Ei missään tärkeysjärjestyksessä, vaan ajattelun ja toiminnan pohjaksi antamaan ryhtiä koodaamiseen Aloita ohjelma infosisältöisillä kommenttiriveillä, täytä ainakin seuraavat tiedot koodin nimi hardware software päiväys, mahdolliset muutokset koodin tekijä(t) lyhyt kuvaus mitä ohjelma tekee Esimerkiksi: /* =========================================================================== * PROJECT DETAILS * =========================================================================== * LICENSE : GNU General Public License Version 2 (GPL) * Author : First Last | email | phone * Company : Telok ry * Date : Date (syntax US: MM/DD/YYYY, EU: DD.MM.YYYY, Archive: YYYYMMDD) * Project : * Desc : * website : * Language: C (Embedded C) * Style : TUT Style++ (http://www.telok.fi/doku.php?projektit:tyyliopas_style_.pdf) * Builder : AVR Studio 7, WinAVR etc... * * Version : * Changes : (or make changelog.txt or use another system) * * HARDWARE DETAILS * Chip type : ATmega32 * Program type : Application * AVR Core Clock frequency: US: 12.000000 MHz EU: 12,000000 MHz * Memory model : Small * External RAM size : 0 * Data Stack size : 512 */ Kommentoi riittävästi, mutta ei itsestäänselvyyksiä. Kommentoi koodin kirjoittamisen ja testaamiseen yhteydessä, myöhemmin et enää muista mitä ohjelma tekee Yksi käsky per rivi Kirjoita ilmavaa koodia, käytä tyhjiä rivejä ja sisennyksiä jäsentämään koodia. On tärkeää, että koodi on myöhemminkin luettavaa ja ymmärrettävää, myös muiden toimesta. Käytä lohkosulkeita järkevästi jäsentämään koodia. Käytä samasta syystä tarvittaessa kaarisulkeita; esim. pitkien ehtolauseiden jäsentämiseen usealle riville. Muuttujat, funkiot ja jäsenfunkiot alkavat pienellä alkukirjaimella, useammasta sanasta koostuvat nimet kirjoitetaan yhteen ja loppupäänsanat aloitetaan isolla kirjaimella; esim readAxisPosition() Jaa ohjelma itsenäisiin funktioihin. Parhaimillaan main()-funktiossa on vain funktiokutsuja. Funktion hyvä koko: koko funktio näkyy ruudulla samalla kertaa. Funktion nimen tulee olla kuvaava ja nimen tulee alkaa pienellä kirjaimella Muuttujat esitetään funktion alussa. Muuttujan nimen tulee olla kuvaava, yksittäinen kirjain sallitaan vain silmukkalaskurissa. Koska AVR usein on 8-bittinen, käytä 8-bittisiä muuttujatyyppejä, char, ja mieluusti, jos mahdollista, etumerkitön char eli uint8_t. Erikoisen tärkeää globaaleille muuttujille. Vältä 16- ja 32-bittisten muuttujien käyttöä, jos se ei koskaan tarvitse niin suurta muistialuetta. Haaskaat turhaan muistia. Local-muuttujia käytetään pääsääntöisesti rekisterissä (niitähän on AVR:ssä paljon, yleensä ainakin 32 kpl), se tuo nopeutta lisää, eli käytä local-muuttujia. Jos on tarvetta (esim. laskuri) käytä funktion sisällä muuttujan määrityksessä static-määrettä. Se muistaa arvonsa funktiokutsujen välillä. Funktion alussa muuttuja siirretään rekisteriin, ja lopussa palautetaan SRAMmiin, se lisää suoritustehoa. Käytä datan siirtoon funktioiden välillä argumentti-parametri ja return määrityksiä (globaalien muuttujien sijasta). Tämä on tärkeää! Jos tarvitset kontrollilippua, esim. muuttujan arvon testauksessa, käytä määritykseen käyttämätöntä rekisteriä. Jos se on muuttujassa, niin lippu pitää hakea muistista rekisteriin ja testin jälkeen palauttaa muistiin. Mutta jos esim UART ei ole käytössä, käytä sen UBRR rekisteriä lippuna, testi nopeutuu. Vakio kopioidaan flashistä SRAMmiin heti ohjelman alussa (startup) ja se säilyy siellä ohjelman ajon ajan, eli se haaskaa SRAMmia. Talleta vakio flash-muistiin erityismääreellä __flash char string[] , ja käytä pointeria kun muuttujaa/tekstiä tarvitaan. Kesketytyksessä kaikki käytettävät rekisterit talletetaan pinoon, stack. Jotta koodi olisi pienikokoista ja nopeaa, keskeytysrutiinin tulisi olla pieni, siellä vaan käydään ja sieltä ei tule kutsua muita funktioita. do{}while on parempi kuin while() tai for(). for(;;) on parempi kuin while(1) selitys Makro on parempi kuin pieni funktio. Käytä I/O-avaruuden osoittamista suoraan, ei pointerilla, nopeuttaa. Oikeastaan mihin on kiire? Mutta muistista on ennen pitkää pulaa… Volatile Jos sulautetun systeemin koodin toiminta muuttuu oudoksi kun kytket kääntäjän optimoinnin päälle tai otat keskeytyksen käyttöön, on syytä opetella tuntemaan volatile-määritys. Tämä on sulautetun järjestelmän eristyspiirre. Kun kääntäjä saa sijoittaa haluamiaan muuttujia muistin sijasta CPU:n rekistereihin, nopeuttaa se ohjelmaa (optimointi). Mutta kääntäjä on siirtänyt jonkun muuttujan rekisteriin ja kesken kaiken tulee keskeytys joka käsittelee juuri tuota muuttujaa - siis sen muistissa olevaa versiota - on tuloksena ongelmia. Volatile sanoo kääntäjälle: älä päästä optimoijaa muuttamaan tätä muuttujaa pitämällä sitä pelkästään CPU:n rekisterissä, koska sen arvo voi muuttua (esim. keskeytysfunktiossa). Jos pidät muuttujaa pelkästään rekisterissä, et huomaa sen muuttumista. Joten aina kun tätä muuttujaa käytetään, se on haettava ja palautettava takaisin RAM-muistiin. Volatile on muuttujan lisämääre, joka kieltää kääntäjää muokkaamasta ohjelmoijan tarkoittamaa koodin toimintaa. Siis kääntäjä ei suorita tälle muuttujalle minkäänlaista optimointia tai muuta järjestelyä. Käyttö: Muuttuja on määritettävä volatileksi, jos sen arvo voi muuttua välittömästä koodista huolimatta. kun muuttujan arvo voi muuttua asynkronisesti, siis esim. kun globaalia muuttujaa muokataan keskeytysfunktiossa ja jota arvoa testaan pääkoodissa samoin jos käytetään muistiavaaruudessa olevaa oheislaitteen rekisteriä jonka arvo voi muuttua koodista huolimatta kun odotetaan loopissa jossa luetaan I/O-pinnin muuttumista tai kun luetaan timeria jos yleensä odotellaan koodissa, että jotain tapahtuu (esim. while(!jotain);) Syntaksi: volatile int arvo; int volatile arvo; ihan miten päin vaan. Muuta luettavaa Style++ tyyliopas PDF-tiedosto (210Kt) projektit/wanhat/hyva_sulautettu_c_koodi.txt Viimeksi muutettu: 2019/09/18 20:31(ulkoinen muokkaus) Kirjaudu sisään