Il 31/05/2013 16:51, Marco Trapanese ha scritto:
> Il 31/05/2013 15:59, pozz ha scritto:
>
>> Se il micretto gestisce frame di lunghezza max 10 byte, posso definire
>> un buffer da 15 e sono a posto... e no! Su un half-duplex tutti gli
>> slave ricevono tutti i frame, anche quelli di altri (evviva la privacy).
>> E se sulla rete ci sono nodi più potenti (il master è sicuramente
>> "potente") che possono gestire frame da 100-200 byte? Devo allocare
>> 100-200 byte sul micretto? E dove li trovo? Devo limitare la lunghezza
>> massima dei frame sulla rete a quella gestibile dai micretti?
>
> Grezzamente: se il micretto sa che al massimo i messaggi indirizzati a
> lui sono di 30 byte, può tranquillamente ignorare (> /dev/null :) )
> tutti quelli più lunghi.
Infatti, solo che nell'ISR di ricezione devo sapere se il frame è per
me, quindi devo fare un minimo di decodifica del frame per conoscere
l'indirizzo destinazione.
>> Non solo, immaginate che:
>> 1. all'istante 0ms il master mandi un frame di 30 byte allo slave 1
>> 2. all'istante 10ms, slave 1 risponde con 10 byte
>> 3. subito dopo aver ricevuto la risposta, il master
>> trasmette 10 byte allo slave 2
>> Se il micretto entra in una routine che dura 100ms all'istante 0ms,
>> quando esce deve aver memorizzato 50 byte, quando la lunghezza del più
>> grande frame è solo 30 byte!!
>
> Questo dipende dalle risorse che hai a disposizione. Puoi anche tentare
> una soluzione ibrida. Quando hai terminato di ricevere un messaggio fai
> solo il controllo del crc (se c'è) e del destinatario.
> Se non è indirizzato a te, sovrascrivi il buffer.
Ma questo vuol dire che devo memorizzarmi, anche temporaneamente per poi
scartarlo subito se non è per me, tutto l'intero frame. Ma se il frame
è da 200 byte ed è diretto al microne, mentre io sono un micretto? Dove
li prendo 200 byte?
La mia proposta (che mi hanno suggerito) era quella di capire subito
nell'ISR di ricezione il destinatario del messaggio e, con una semplice
macchina a stati, scartare tutti i byte di un frame destinato ad altri.
> Questo funziona se nel periodo in cui non puoi dedicarti
> all'elaborazione dei dati ricevuti può arrivarti un solo pacchetto a te
> destinato.
>
> E' chiaro che se così non fosse c'è poco da fare:
>
> - buffer più grande
> - micro più veloce
> - evitare di utilizzare routine bloccanti
Infatti, invece con la piccola complicazione dell'ISR che ho proposto,
anche se dovessero arrivare 100 frame di 100 byte per altri slave, il
micretto li scarterebbe tutti e vivrebbe bene con il suo bufferino da 15
byte.
>> Si può risolvere la cosa elegantemente e permettere la connivenza di
>> micretti e microni complicando leggermente l'ISR di ricezione sugli
>> slave e definendo il protocollo in modo che dai primi byte già si
>> capisca a chi è indirizzato il frame. Se è per il micretto, allora il
>> frame verrà salvato nel buffer (che potrà essere dimensionato sulla
>> massima lunghezza dei frame gestiti da *quello* slave e non dagli
>> altri), altrimenti verrà scartato fino all'ultimo byte.
>
> Si, ma devi fidarti che i byte siano ricevuti correttamente visto che
> non puoi fare alcun controllo di integrità.
Sì, mi devo fidare almeno del byte che indica l'indirizzo destinazione.
Ma non è così grave. Infatti, come dicevo, l'eccesso di fiducia può
creare problemi solo se il byte di destinazione è corrotto e può essere
corrotto in due modi.
Se il frame è per un altro e l'indirizzo è corrotto e *appare* per me,
lo memorizzo, ma poi lo ignoro alla fine per CRC errata. Dovesse essere
un frame più grande del mio buffer, comunque lo scarterei.
Se il frame è per me e l'indirizzo è corrotto e *appare* per un altro,
quell'altro alla fine ignorerà il frame per CRC errata e il master non
avrà risposta... quindi ritrasmissione.
In tutti i casi, l'eccesso di fiducia non porta a grosse conseguenze.
> A seconda dei casi può
> essere un problema, oppure una strada accettabile.
> Poi non credo sia una buona idea mettersi a fare queste cose nell'isr
> nel mezzo della ricezione di un pacchetto.
In realtà è una macchina a stati finiti veramente semplice.
>> E come capisco la fine di un frame? E' sufficiente delimitare i frame
>> con un byte di SYNC: per esempio, un frame inizia e finisce con un
>> carattere di SYNC e i caratteri di SYNC ed ESC presenti nel payload si
>> trasformano in sequenze di escape ESC ESC_SYNC e ESC ESC_ESC (tipo SLIP).
>
> Io di solito utilizzo un carattere di fine pacchetto (\n nel caso di
> dati ascii o 0x03 per i dati binari (ma appunto con l'accortezza del
> payload) associato a un timeout sul carattere.
Se il pacchetto viene delimitato all'inizio e alla fine (con lo stesso o
con un byte diverso), penso che il meccanismo del timeout non serva.
In genere il timeout serve per affrontare situazioni in cui il pacchetto
non arriva tutto. Ma se hai un byte di inizio pacchetto, l'eventuale
precedente pacchetto a metà verrà comunque scartato (per CRC errata o
errore di sintassi o qualcosa di simile).
Da quando ho capito questo, mi sono subito levato di mezzo il timeout
che crea solo problemi (a quanto lo metto? è tra un byte e l'altro o tra
il primo byte e la fine del pacchetto?...)
>> Che si fa se i frame sono protetti da CRC? Come faccio nell'ISR a
>> guardare l'indirizzo destinazione se non controllo prima la CRC? Poco
>> male, lo guardo lo stesso.
>
> Allora non serve il CRC ;)
Come dicevo su, l'eccesso di fiducia che il byte destinazione sia
corretto pur non avendo controllato la CRC non crea particolari problemi.
>> Però c'è un altro inghippo... nella rete ho dei frame broadcast che, per
>> ovvie ragioni, non hanno risposta. Il master potrebbe inviare un bel
>> SET CLOCK a tutti gli slave e poi iniziare a fare un polling. Se il
>> master non fa una pausa dopo un frame di broadcast, al micretto arrivano
>> ben 2 frame prima che possa processarli e allora l'implementazione di
>> prima non va bene.
>
> In generale il dimensionamento dovrebbe sempre tenere conto del worst-case.
> Questo però lo puoi gestire tu a livello di progettazione.
>
>
>> Ok, risolvo facilmente dicendo al master di prendersi un caffè dopo un
>> frame di broadcast (quanto durerebbe questo caffè? dovrebbe essere
>> dimensionato sullo slave più lento)... ma perchè dargli questo
>> privilegio? Lo pago per lavorare, non per prendersi il caffè.
>
> Non sei corretto! Dai anche agli slave le stesse risorse del master e
> vedi se non ti stanno dietro! ;)
E chi le paga tutte queste risorse, quando in realtà non servono per
molti slave? :-)
>> Allora penso che posso aggiungere un secondo livello di framing, uno
>> nell'altro: uno a livello più basso per l'ISR e l'altro a livello più
>> alto per la funzione di gestione della rete... ma ho la sensazione di
>> stare esagerando!
>>
>> Voi vi fate tutti sti problemi?
>
> Non esiste una soluzione ottimale per tutte le situazioni.
> Nel caso specifico, individua i vincoli che non puoi cambiare e su
> quelli basati per dimensionare il resto.
Beh, mi sarebbe piaciuto creare un protocollo di rete che potesse andare
bene nella maggior parte delle situazioni che mi trovo ad affrontare,
più o meno sempre le stesse.
Immagina Ethernet, non penso sia stata disegnata con una precisa
applicazione in mente (basso bitrate, streaming multimediale, VoIP,
...). L'obiettivo è massimizzare il throughput a partire da una certa
capacità di canale (10 o 100Mbps).
E' grosso modo quello che cercavo di fare: ho una RS485 a 9600bps, posso
inventarmi qualcosa per risolvere tutti i problemi comuni e massimizzare
il throughput?
> A mio modesto parere, a meno di numeri elevatissimi, in generale
> conviene investire qualche cent in più per non essere strozzati con le
> risorse hardware e implementare un firmware semplice e lineare piuttosto
> che sputare sangue per risparmiare una manciata di byte.
Sì, è chiaro.
Ma alla fine devi pur sempre dimensionare i buffer in modo scientifico,
cioè in modo che deterministicamente, se non ci sono errori di
trasmissione, il frame non venga perso. Non penso che alla NASA (o
anche alla Volkswagen) si mettano a dimensionare i buffer "a naso".