Tema: Re: del uart'o
Autorius: saimhe
Data: 2010-07-02 18:17:17
> tipo jeigu turiu amzina cikla kuris vis sukasi su kazkokiais veiksmai jame, tai vis patikrinu uarto baita, sakykim kazkoks spec
> pradzios baitas.

  Dažnai interrupt'e galima padaryti visą ryšio protokolą 100% ir tas
pagrindinis ciklas apie tai nieko nežinos.
  Tai yra kodo gabalas, kurį pradeda vykdyti automatiškai. Blinkini
sau led'us, o procas staiga perdavė valdymą kitai paprogramei,
atėjusiam baitui apdoroti. Apdorojo, grįžo -- procas tęsia savo amžiną
ciklą. Automatiškai pradeda vykdyti nuo tam tikro adreso (interrupt
vector), paprastai tenai įrašomas jump'as į paprogramę; C kalboje viską
apiformins kompiliatorius. Taip pat sisteminiuose registruose reikia
įjungti generavimą (interrupt enable bit, ir taip toliau). Be to, yra
ir bendras "enable", su juo trumpam pristabdomi interrupt'ai, kada labai
jau negalima trukdyti maždaug keliolikos komandų trukmės veiksmams.
  Idėja pasiteisina, jei kiekvieno baito apdorojimas yra minimaliai
trumpas -- tik todėl jis netrukdo pagrindiniam ciklui. Kartais visvien
trukdo, tada reikia imtis priemonių.

  Žymiai paprasčiau, kai gaunami paketai turi griežtą struktūrą.
  Tarkim, protokolas yra tekstinio tipo: ":" -- pradžios baitas, kurio
niekada nebūna tarp duomenų; "0"..."F" -- toliau esančių įrašų skaičius
minus vienas; "00" ... "FF" -- duomenys, nuo 1 iki 16 tokių porų. Būtų
dar galima pabaigoje pridėti 0Dh arba 0Ah, kartais tai naudinga, jei
priima kompas -- pavyzdžiui, tiek Win32, tiek Linux sugeba reaguoti į
tokį baitą sraute ir tik po to grąžinti visą priimtą paketą (nereikia
pačiam rinkti po baitą).
  Tai dabar pravartu žinoti, kas yra baigtinis automatas (finite state
machine). O galima ir nežinant aklai įprasti naudoti būsenos kintamąjį,
iš kurio (ir kitų pagalbinių kintamųjų) visada aišku, ką daryti su naujai
atėjusiu baitu. Reikšmėms C kalboje naudojami enum arba #define (pvz.,
enum { ST_IDLE = 0, ST_PREAMBLE, ST_LENGTH, ST_D0H, ST_D0L ... }).
Panašios simbolinės priemonės yra ir asembleryje. O šitas mūsų protokolas
toks paprastas, kad pakenčiamai atrodys ir pliki skaičiai 0 ... 34,
tiesiog ne taip vaizdu. Patogu, kai reikšmės tolygiai didėja -- galima
būsenos kintamąjį didinti vienetu.
  Gavom baitą, būsena 0 -- jei baitas ne ":", ignoruojam ir būsena
lieka 0.
  Būsena 1 -- gautas baitas turi būti nuo "0" iki "F" (30h ... 39h,
41h ... 46h). Jei ne, tada duomenys sugadinti ir priiminėsim iš naujo,
būsena grįžta į 0. Jei normalus šešioliktainis skaičius, tada verčiam
į binary ir įsimenam kaip paketo ilgį.
  Būsena 2...33: lygiai taip pat tikrinama reikšmė ir verčiama į binary.
Lyginiais atvejais dauginam iš 16 (arba pastumiam per 4 bitus) ir
įsimenam, o nelyginiais -- operacija "OR" su įsiminta reikšme ir įrašom
į buferį adresu (busena - 2) / 2. Įrašius tiek baitų, kiek buvo nurodyta
paketo ilgyje, būsena pavirsta 34: laikas apdoroti. Tai signalas
pagrindiniam ciklui, kad buferis pilnas. Tenai, jo turinį panaudojus,
būseną reikės grąžinti į 0.
  Interrupt'e būsena vis dar 34 -- baitą ignoruojame, nes buferis vis
dar pilnas.

  Beje, panašiai padaromas ir siuntimas. Iškeliavus eiliniam baitui,
susigeneruoja siuntimo interrupt'as. Paprogramė ima iš buferio naują
baitą ir permeta į siuntimo registrą. Jei baitų nebėra, nebereikia ir
nieko daryt.

-- 
  saimhe