AngoLinux

Definizione del protocollo di comunicazione con scheda micro

- A cura del Prof. Stefano Salvi -


La connessione tra l'host e la CPU 8052 è effettuata tramite una linea seriale. Dato che la connessione è realizzata tramite un cavo di lunghezza limitata, non si prevedono errori, salvo in caso di guasto hardware.

D'altro canto, una perdita di dati dovuta a ritardi nella risposta del software và messa in conto.

Dobbiamo fare in modo che ogni comando riceva una risposta per garantire la sua corretta ricezione, in caso contrario il mittente dovrà inviare di nuovo il comando fintantochè non riceverà una risposta, fino ad un massimo di cinque ritentativi, dopo di che assumerà che il comando sia stato perso.

Definizioni

Comando: è un messaggio che richiede al ricevitore dall'altro capo di svolgere una determinata azione. Può essere una richiesta di informazioni (ad esempio, 'Stato attuale dei pulsanti') o semplicemente la richiesta di un'azione (ad esempio 'scrivi caratteri sul display'). Nel primo caso all'altra parte è richiesto di inviare una risposta che contiene i dati voluti, mentre nel secondo caso l'altra parte deve semplicemente eseguire un'azione.

Risposta: è un messaggio che trasporta i dati richiesti da un precedente comando. Una risposta non richiede conferma, in quanto se viene persa o ricevuta male, il comando che l'ha provocata verrà rispedito.

Conferma: è un particolare messaggio di risposta che indica che un comando è stato correttamente ricevuto. Verrà inviato in risposta a tutti quei comandi che non richiedono dei dati risposta.

Framing

Dato che esiste una possibilità di perdita di dati, non possiamo fare affidamento sul fatto che un comando sia corretto e che i dati ricevuti siano completi. Se perdiamo il byte del comando, il primo byte del dato verrà interpretato come comando, creando la possibilità che venga eseguito per sbaglio.

Dobbiamo prendere in considerazione la possibilità di incapsulare tutti i messaggi (comandi o risposte/conferme) in trame.

Per la struttura della trama ci possiamo ispirare al PPP in HDLC-like Framing (PPP - Point to Point Protocol - in trame simili all' HDLC - High level Data Link Control) come descritto nella RFC 1662. Dato che la linea è considerata sicura, si adotta uno schema di controllo semplificato, come segue

FLAG DATI CHECKSUM FLAG

FLAG: ogni trama è delimitata da due caratteri di flag (uno di apertura ed uno di chiusura). Il valore del carattere di flag è 7E HEX. Il valore esadecimale 7E non può comparire tra i dati, altrimenti la trama corrente verrebbe chiusa erroneamente. Se si deve trasmettere un dato il cui valore sia 7E HEX, questo dato viene mascherato, facendolo precedere dal carattere esadecimale 7D e viene trasformato in 5E HEX (7E XOR 20) per evitare che la perdita accidentale del 7D causi una chiusura accidentale della trame. Se si deve a questo punto trasmettere un dato il cui valore sia 7D, si applica lo stesso mecanismo, trasmettendo 7D 5D (7D XOR 20). In questa maniera le uniche sequenze 7E che saranno trasmesse sulla linea saranno sequenze di FLAG. Ogni trama dovrà essere incapsulata in mezzo alla sua coppia di flag.

DATI: è il pacchetto di dati da trasmettere. Si può trasmettere un massimo di 253 caratteri. Il primo byte in ogni pacchetto è un byte di comando.

CHEKSUM: è l'inverso della somma di tutti i byte del pacchetto (esclusi i flag) troncata ad 1 byte. Il checksum va calcolato prima di applicare le regole di trasparenza sopra spiegate

La lunghezza massima del pacchetto (valida solo per i pacchetti inviati dall'host alla scheda) è stata calcolata considerando che il display contiene 250 colonne e che un comando che invii una sequenza grafica completa dovrà essere lungo 250 colonne, più le coordinate ed il comando stesso.

Dobbiamo tener conto che ci serviranno due buffer in ogni direzione (uno per un comando ed un'altro per una risposta).

Regole del Protocollo

  1. Ogni carattere ricevuto al di fuori di una trama và scartato. Non sono ammesse trame back to back, vale a dire che condividono il flag.
  2. La sequenza FLAG FLAG (7Eh 7Eh) deve venir considerata un singolo flag (è il possibile risultato della perdita di un flag di apertura: il flag di chiusura è il primo dei due flag, il secondo è il flag di apertura della trama corrente, il contenuto della trama precedente è stato scartato in base alla regola 1).
  3. Ogni trama con un checksum sbagliato và scartata
  4. Ogni comando/risposta/conferma è codificato in un singolo byte
  5. Ogni comando che non prevede una risposta deve prevedere una conferma
  6. Una risposta è una trama contenete i dati richiesti da un comando. Il codice della risposta corrisponde al codice del comando cui risponde, con il bit più significativo settato.
  7. Una trama di risposta ha il seguente formato:
    Flag Risposta Dati della Risposta Checksum Flag
  8. Una conferma è una trama contenete un solo byte di dati, composto dal solo codice (FFh = conferma). L'intera trama sarà dunque composta dalla seguente sequenza esadecimale: 7E FF FF 7E, in forma grafica:
    Flag Conferma Checksum Flag
  9. Una risposta o una conferma possono essere distinti da un comando perché il loro comando possiede il bit più significativo ad 1.
  10. Prima di aver ricevuto la risposta/conferma di un comando non è possibile inviare altri comandi (ma ne può essere ricevuto uno)
  11. Un comando può essere inviato dall'host (il caso normale)
  12. Un comando può anche essere inviato dalla scheda (notifica di evento sulla tastiera) (questo rende il protocollo simmetrico)
  13. I byte di una trama vanno inviati uno dopo l'altro, senza inserire pause
  14. Il ricevitore deve implementare un timeout per scartare una trama, nel caso non arrivasse in tempo (utile nel caso venisse perso il flag 7E di chiusura)
  15. Anche la conferma/risposta deve essere inviata immediatamente alla ricezione del flag di chiusura della trama del comando. Si potrà usare un timeout più lungo per rilevare la mancanza di risposta
  16. Il timeout tra due caratteri ricevuti uno dopo l'altro deve essere maggiore di 4 tempi di carattere al boud rate corrente. Nel nostro caso sceglieremo 110 mS, equivalente a 2 timer ticks del PC (nel PC imposteremo 55mS, per garantire un timeout compreso tra 55 e 110 mS, nell'8052, con clock a 11,0592 MHz, questro ritardo si ottiene con un timet a 5mS - divisore 60298 - impostando il timeout a 22 'tick'). Un timeout così lungo ha un impatto limitato sulle prestazioni del protocollo. Se non arrivano più caratteri, trascorso questo timeout la trame è considerata terminata am non chiusa (non è stato ricevuto il flag di chiusura) e quindi scartata. Questo meccanismo è implementato nella macchina a stati del ricevitore di basso livello.
  17. Il timeout più lungo tra la fine della ricazione di un comando e la ricezione della conferma/risposta è fissato in 495mS (da 440 a 495 mS per il PC - 99 tick per la scheda). La macchina a stati della trasmissione si occuperà di gestire questo timeout. La lunghezza massima di una trama è di 256 byte (253 dati + 2 flag + 1 checksum) ma, considerando il fatto che questi dati possono venir mascherati, questa dimensione può diventare 510. Un massimo teorico di 510 + 4 = 514 tempi di byte serve per trasmettere una coppia comando/risposta (occorre ricordare che un conamdo con dei dati avrà una trama di conferma di 4 byte, non una risposta più lunga con dei dati). Occorre aggiungere che questa lunghezza massima è relativa solo ai comandi originati dall'host. I comandi generati dalla scheda (stato dei pulsanti) saranno composti da un comando di 5 byte (comando più un parametro) ed una conferma di 4 byte, quindi 9 byte in totale. Se viene inviato un comando dall'host e, prima che arrivi la risposta, arriva un comando dallo slave, avremo un massimo di 514 + 9 = 523 caratteri. A 9600 baud (tenendo in considerazione anche i bit di start e di stop) questo porta a 544 mS. Utilizzeremo quindi un timeout di 660 mS (da 605 a 660 mS) che garantisce un sufficente margine. Se questo timeout scade senza che sia giunta la risposta, considereremo che sia avvenuto un errore e il comando dovrà essere ritrasmesso, per un massimo di 5 volte.
  18. È possibile che entrambe le parti inizino a trasmetter un comando simultaneamente. In questo caso la conferma o risposta verrà ritardata fino al termine della trasmissione della trama corrente, ma questo ritardo non è tale da far scattare il meccanismo della ritrasmissione.

Sviluppo del protocollo

Questo protocollo si sviluppa su due livelli.

  1. : macchina a stati SerialTx, macchina a stati SerialRx
  2. : macchina a stati Transmitter,macchina a stati Receiver

Implementazione su 8052

Entrambe le macchine a stati del primo livello saranno implementate nella routine di risposta all'interrupt seriale

  • SerialTx parte quando un kickoff (un byte 7E hex) è inviato dal livello superiore; legge il pacchetto da inviare da un buffer, (scelto in base al tipo di invio: comando o risposta) e lo trasmette, calcolando nel contempo il checksum, rispettando le regole di trasparenza, quindi invia il chacksum ed il 7E hex di chiusura.

  • SerialRx parte quando viene ricevuto un byte di flag, di valore 7E hex; riceve una trama, ricostruendo i caratteri mascherati e calcolando il checksum; alla ricezione del flag di chiusura, verificherà il checksum e, se sarà corretto, segalerà all'opportuno livello superiore, in base al tipo di pacchetto ricevuto, l'avvenuta ricezione, attivando un flag.

Nel secondo livello, il ricevitore è implementato nella procedura in foreground, in mainera procedurale e non come automa, mentre il ricevitore è implementato nella procedura di risposta all'interrupt del timer 0.

  • Il trasmettitore è attivato settando un flag. Invia semplicemente un kickoff (se necessario) per avviare SerialTx ed attende 495 mS una risposta. Se, durante questo tempo, SerialRx non avvisa della ricezione di una risposta, il trasmettitore reinvia il comando. Il trasmettitore si ferma o quando è ricevuta una risposta o quando sono state effettuate 5 ritrasmissioni.

  • Il ricevitore è attivato quando SerialRx attiva il flag di comando ricevuto. Esamina il byte di comando ed esegue l'azione relativa, quindi invia la conferma o risposta tramite SerialTx. L'azione non deve richiedere troppo tempo, in quanto altrimenti potrebbe scattare il timeout del trasmettitore dell'altra parte.

Implementazione su PC

Dobbiamo gestire indipendentemente tre flussi:
  • Ingresso seriale
  • Uscita seriale
  • Ingresso da tastiera (stdin)
ed inoltre dobbiamo gestire dei timeout. Per ottenere tutto questo occorre utilizzare la funzione select.

Comandi

Dall'Host

Richiesta stato Tasti
  • Codice Comando: hex 10
  • Parametri: Nessuno
  • Risposta/Conferma: hex 90, seguito dal byte con lo stato dei tasti
  • Descrizione: questo comando consente di richiedere alla scheda lo stato attuale dei tasti. Il byte inviato come risposta conterrà, nei bit bassi, lo stato nuovo dei pulsanti (0 -> rilasciato, 1 -> premuto) per ciascuno dei quattro pulsanti presenti sulla scheda del display.
Reset Display
  • Codice Comando: hex 52
  • Parametri: Nessuno
  • Risposta/Conferma: Conferma
  • Descrizione: Questo comando cancella e resetta il contenuto del display.
Scrittura Caratteri su Display
  • Codice Comando: hex 21
  • Parametri: colonna (0..40) espressa in celle di carattere, riga (0..1), caratteri da scrivere (non terminati con NULL)
  • Risposta/Conferma: Conferma
  • Descrizione: scrive i caratteri indicati, a partire dalla colonna indicata, nella riga indicata. I caratteri sono scritti in una cella di 8 righe e 6 colonne. Se i caratteri inviati sono più di quelli che stanno nella riga corrente, i caratteri in eccesso sono scartati.
Scrittura Pixel su Display
  • Codice Comando: hex 22
  • Parametri: colonna (0..249) espressa in pixel, riga (0..1), colonne di pixel da scrivere
  • Risposta/Conferma: Conferma
  • Descrizione: scive le colonne di pixel inviate, a partire dalla colonna indicata, nella riga indicata. Ogni colonna di pixel è costituita da otto bit, corrispondenti ad otto pixel. Il bit più significativo corrisponde al pixel più in basso, il meno significativo a quello più in alto, 0 corrisponde a pixel spento, 1 a pixel acceso. Se le colonne inviate sono più di quelle che stanno nella riga corrente, le colonne in eccesso sono scartate.
Richiesta Stringa Versione
  • Codice Comando: hex 44
  • Parametri: Nessuno
  • Risposta/Conferma: hex C4, seguito dalla stringa di caratteri null terminated (stile C) contenete la denomiunazione e versione del software.
  • Descrizione: questo comando consente di richiedere alla scheda una stringa di presentazione. La stringa sarà una stringa stampablie, contenete, nell'ordine, il nome del prodotto, un '-', il nome del produttore/programmatore, un ':', la stringa della versione 'v.M,m', dove M è il numero maggiore di revisione, una cifra, e m è il numero minore di revisione, sempre una cifra.

Dalla scheda

Cambiamento stato Tasti
  • Codice Comando: hex 16
  • Parametri: il byte contenete il nuovo stato dei tasti, nei quattro bit bassi
  • Risposta/Conferma: Conferma
  • Descrizione: questo comando viene inviato dalla scheda tutte le volte che rileva un cambiamento nello stato dei tasti (pressione o rilascio). Il byte inviato come parametro conterrà, nei bit bassi, lo stato nuovo dei pulsanti (0 -> rilasciato, 1 -> premuto) per ciascuno dei quattro pulsanti presenti sulla scheda del display. La scheda gestirà la logica di antirimbalzo, inviando un evento appena viene rilevato un cambiamento nello stato dei tasti, quindi attendendo 100mS prima di rilevare di nuovo lo stato dei tasti. In questo modo, al nuovo rilevamento dello stato il transitorio del tasto si sarà esaurito.

[Scarica il tarball con il programma per la scheda]


[Home Page dell'ITIS "Fermi"] [Indice Quinta] [Precedente] [Successivo]

© Ing. Stefano Salvi - Released under GPL licence