Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Quale protocollo flessibile per una rete di nodi half-duplex

22 views
Skip to first unread message

pozz

unread,
May 31, 2013, 9:59:31 AM5/31/13
to
Sono partato da comp.arch.embedded
(groups.google.com/forum/?fromgroups#!topic/comp.arch.embedded/vLKKGvdH6oI),
ma mi sembrava utile discuterne anche qui.

Stavo mettendo su una "classica" rete RS485 a 2 fili (anche se il
livello fisico poco importa) con 1 master ed N slave. Durante
l'implementazione del protocollo su uno slave basato su un piccolo e
lento micro a 8 bit, mi sono chiesto come dimensionare il buffer di
ricezione. Potevo farlo come al solito "a senso", ma ho fatto l'errore
di adottare un approccio un po' più scientifico, ed ora non so più che
pesci prendere :-)

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?

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!!

In altre parole, sembra che la dimensione del buffer su un qualsiasi
nodo dipenda anche dalla dimensione massima del frame più lungo (anche
diretto ad altri slave), dai tempi di risposta degli slave veloci e da
quanto veloce è il master a trasmettere un successivo frame... povero
micretto!

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.

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).

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.
Se il frame è per un microne e l'indirizzo destinazione è corrotto e
coincidente con un micretto, potrei correre il rischio di memorizzare un
frame grande nel buffer piccolo del micretto, ma all'overflow del buffer
lo andrei a scartare (tanto non era sicuramente per il micretto).
Se, invece, il frame è per il micretto ma l'indirizzo destinazione è
corrotto, il frame non verrà memorizzato/processato e il master non
vedrà risposta, con conseguente ritrasmissione.

Quindi semplice implementazione: un buffer/array buf[] dove memorizzo
tutti i frame per me (lo vedo dal primo byte dopo il SYNC) partendo da
buf[0]. Ad ogni SYNC e buffer non vuoto (per gestire il doppio SYNC),
disattivo la ricezione, processo il frame (con tutto comodo), trasmetto
la risposta, resetto il puntatore a buf[0] e riattivo la ricezione.
Semplice e pulito.

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.

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è.

Allora inizio a pensare che l'implementazione della ricezione può essere
fatta su una FIFO: ogni byte che appartiene ad un frame per me o
broadcast viene pushato nella FIFO. La routine di gestione dei
pacchetti farà pop, un byte alla volta... ma come farà a distinguere la
fine di un pacchetto (la decodifica dei caratteri di SYNC è stata già
fatta al volo nell'ISR, perchè devo leggere l'indirizzo destinazione),
visto che potrebbe esserci un secondo?

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?


Marco Trapanese

unread,
May 31, 2013, 10:51:06 AM5/31/13
to
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.


> 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.

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



> 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à. 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.


> 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.


> 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 ;)


> 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! ;)


> 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.

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.

Ciao!
Marco


Francesco Sacchi

unread,
May 31, 2013, 11:08:27 AM5/31/13
to
Il 31/05/2013 15:59, pozz ha scritto:
> Voi vi fate tutti sti problemi?

Sinceramente, no, non capisco il problema.

Ti dico come faccio di solito io.

Sotto ISR metto i caratteri in una fifo lunga al massimo quando il
massimo pacchetto che voglio gestire.

Se la fifo ᅵ piena, i caratteri successivi li butto via.

Poi c'ᅵ un processo da qualche parte che snocciola i dati dalla fifo e
controlla per i vari STX, ETX, CRC e indirizzo di destinazione.

Se il pacchetto contiene l'indirizzo dello slave lo processo, altrimenti no.

Puᅵ succedere che lo slave perda qualche pacchetto perchᅵ intasato da
quello che passa sulla rete, ma come dicevi tu il master ᅵ piᅵ furbo e
puᅵ effettuare una ritrasmissione se non riceve risposta.

Cosa c'ᅵ che non va in questo approccio?

Ciao



dalai lamah

unread,
May 31, 2013, 1:33:31 PM5/31/13
to
Un bel giorno pozz digitň:

> 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.
>
> 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).
>
> 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?

Mi sembra che tu voglia dare un respiro estremamente generale a cose che
non hanno bisogno di esserlo. Bisogna differenziare caso per caso in base
al "key driver" specifico della tua applicazione (efficienza, transfer
rate, fault tolerance, ecc); non ha senso inventarsi un protocollo che vada
bene per trasferire due temperature a 1 Hz o dieci video 1080p
multiplexati.

Quasi tutti i protocolli semplici che ho visto hanno dei frame composti da
tre parti: un header fisso iniziale, un blocco di dati di dimensione
variabile, e un CRC finale. Quindi basta che tutti i micretti ricevano
l'header, dove c'č scritto tutto quello che gli serve per sapere se gli
interessa e la lunghezza del pacchetto. Se non gli interessa, i byte
successivi del pacchetto saranno ricevuti ma ignorati.

--
Fletto i muscoli e sono nel vuoto.

pozz

unread,
May 31, 2013, 5:37:43 PM5/31/13
to
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".

pozz

unread,
May 31, 2013, 5:53:57 PM5/31/13
to
Il 31/05/2013 17:08, Francesco Sacchi ha scritto:
> Il 31/05/2013 15:59, pozz ha scritto:
>> Voi vi fate tutti sti problemi?
>
> Sinceramente, no, non capisco il problema.
>
> Ti dico come faccio di solito io.
>
> Sotto ISR metto i caratteri in una fifo lunga al massimo quando il
> massimo pacchetto che voglio gestire.
>
> Se la fifo è piena, i caratteri successivi li butto via.
>
> Poi c'è un processo da qualche parte che snocciola i dati dalla fifo e
> controlla per i vari STX, ETX, CRC e indirizzo di destinazione.
>
> Se il pacchetto contiene l'indirizzo dello slave lo processo, altrimenti
> no.
>
> Può succedere che lo slave perda qualche pacchetto perché intasato da
> quello che passa sulla rete, ma come dicevi tu il master è più furbo e
> può effettuare una ritrasmissione se non riceve risposta.
>
> Cosa c'è che non va in questo approccio?

Magari mi sbaglio, ma IMHO non è detto che funzioni! Attenzione, è il
classico approccio che avrei usato io, ma poi mi sono messo a pensare...

Per quello che hai detto, lo slave S1 che gestisce al massimo pacchetti
di lunghezza massima di 10 byte, avrà un buffer di 10 byte, giusto? Ma
in una rete half-duplex tutti vedono tutto, quindi quello slave S1
vedrà/riceverà anche il frame da 100 byte diretto allo slave S2.

Tu dici che non è un problema, quando la FIFO è piena gli altri byte
vengono scartati. Ma intato ti sei riempito la FIFO con byte inutili e,
magari, quando arriva il frame per te il processo che snocciola i dati
della FIFO non è stato ancora chiamato (immagina che S1 abbia processi
"lenti", mentre S2 è velocissimo a rispondere) e così perdi il tuo frame.

Tu dici che ogni tanto può capitare, tanto ci sono le ritrasmissioni...
però, se la rete è fatta in un certo modo, questi eventi capitano
deterministicamente.

Immagina il master M, lo slave S1 e lo slave S2. Rete a 9600bps
(8,n,1). S1 gestisce pacchetti massimi di 10 byte, quindi ha un buffer
di 10 byte.
- All'istante 0 S1 entra in un processo bloccante P che dura 100ms
- Subito dopo, M invia 30 byte (31ms) a S2
- All'istante 35ms, S2 risponde con 10 byte (10ms)
- All'istante 35+10=45ms, M riceve tutta la risposta da S2
- All'istante 50ms, M invia 10 byte (10ms) a S1
- All'istante 50+10=60ms, S2 è ancora nel processo P e la FIFO
è piena e il "suo" frame è stato perso

Forse questa sequenza "sfigata" di eventi non capita praticamente mai,
perchè gli slave sono tutti uguali (sia come micro che come firmware).
Però non è sempre così.

Poi il master potrebbe prendere il respiro prima di iniziare una nuova
transazione sulla rete, ma per massimizzare il thoughput sarebbe meglio
che non lo facesse.

pozz

unread,
May 31, 2013, 6:20:53 PM5/31/13
to
Il 31/05/2013 19:33, dalai lamah ha scritto:
> Un bel giorno pozz digitò:
>
>> 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.
>>
>> 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).
>>
>> 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?
>
> Mi sembra che tu voglia dare un respiro estremamente generale a cose che
> non hanno bisogno di esserlo. Bisogna differenziare caso per caso in base
> al "key driver" specifico della tua applicazione (efficienza, transfer
> rate, fault tolerance, ecc); non ha senso inventarsi un protocollo che vada
> bene per trasferire due temperature a 1 Hz o dieci video 1080p
> multiplexati.

Certamente, però potrei trovare un protocollo che massimizzi il
throughput a parità di capacità della rete, minimizzando le risorse dei
singoli nodi.

In altre parole, se ho una RS485 a 9600bps, l'ideale sarebbe poter
inviare dati a quella velocità. Se, però, il protocollo, per come è
definito, deve prevedere delle pause o dei feedback/ack, il throughput
diminuisce.

Un po' come per Ethernet. Ho un canale a 100Mbps (per esempio) e cerco
di fare in modo di massimizzare il throughput, indipendemente se
l'applicazione è un VoIP, uno streaming, un web browsing o chissà cos'altro.


> Quasi tutti i protocolli semplici che ho visto hanno dei frame composti da
> tre parti: un header fisso iniziale, un blocco di dati di dimensione
> variabile, e un CRC finale. Quindi basta che tutti i micretti ricevano
> l'header, dove c'è scritto tutto quello che gli serve per sapere se gli
> interessa e la lunghezza del pacchetto. Se non gli interessa, i byte
> successivi del pacchetto saranno ricevuti ma ignorati.

Ma anche in questo caso, a livello di progetto, il protocollo *deve*
specificare altro per poter funzionare. E cioè deve dire come risolve
il problema del controllo di flusso.

Non è pensabile che il master invii in continuazione pacchetti ad uno
stesso slave alla massima velocità (la larghezza di banda del canale
fisico della rete), altrimenti lo slave, prima o poi, inizierà a perdere
dati per FIFO full.

Una possibilità è quella di prevedere sempre una risposta ad ogni
pacchetto di "andata". In pratica la risposta, oltre a darmi
eventualmente dati utili, mi darebbe l'ok ad inviare il successivo
pacchetto. Appunto il controllo di flusso.

Ma così escludo la possibilità dei pacchetti broadcast che non hanno
risposta. E se voglio i broadcast? Allora non posso fidarmi della
risposta per avere l'ok per la successiva trasmissione. E allora come fare?

Soluzione semplice e non efficiente: tempo d'attesa tra un pacchetto
broadcast e il successivo. Ma come quantificare questo tempo d'attesa?
Dovrebbe dipendere dal tempo massimo che il più lento slave può
impiegare ad elaborare un pacchetto broadcast e a liberare la FIFO,
almeno in parte.

Soluzione più raffinata che tentavo di ideare: lo slave S dovrebbe avere
un buffer delle dimensioni di N broadcast consecutivi trasmessi senza
interruzione (anche N deve essere specificato nel protocollo) + 1
pacchetto massimo per il singolo slave.
Gli N broadcast andrebbero in tutte le FIFO di tutti gli slave, mentre
il pacchetto "normale" andrebbe solo nella FIFO dello slave indirizzato
(sempre insieme agli N broadcast).

Ragionavo su come il processo che si snocciola la FIFO potesse
individuare gli N+1 pacchetti originali se le delimitazioni sono state
eliminate durante la ricezione.
Ma anche qui si potrebbero trovare altre soluzioni: aggiungo altre
delimitazioni a livello più alto, oppure evito di tagliare le
delimitazioni del livello fisico (anche se serve decodificarle per
guardare all'header e all'indirizzo), o altro ancora di più complicato.


Sì lo so, è un periodo in cui non so cos'altro fare :-)

Marco Trapanese

unread,
Jun 1, 2013, 5:56:37 AM6/1/13
to
Il 31/05/2013 23:37, pozz ha scritto:

> 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?


Se fosse indirizzato al micretto sarebbe lungo al massimo 30 byte. Non
vedo il problema.


> 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).


Sicuramente. Mi riferivo al caso di pacchetti binari eventualmente senza
delimitatori.


Ciao!
Marco

SB

unread,
Jun 1, 2013, 6:52:43 AM6/1/13
to
Il giorno Fri, 31 May 2013 23:53:57 +0200, pozz <pozz...@gmail.com> ha scritto:

>Il 31/05/2013 17:08, Francesco Sacchi ha scritto:
>> Il 31/05/2013 15:59, pozz ha scritto:
>>> Voi vi fate tutti sti problemi?

>
>Magari mi sbaglio, ma IMHO non è detto che funzioni! Attenzione, è il
>classico approccio che avrei usato io, ma poi mi sono messo a pensare...
>
>Per quello che hai detto, lo slave S1 che gestisce al massimo pacchetti
>di lunghezza massima di 10 byte, avrà un buffer di 10 byte, giusto? Ma
>in una rete half-duplex tutti vedono tutto, quindi quello slave S1
>vedrà/riceverà anche il frame da 100 byte diretto allo slave S2.
>
>Tu dici che non è un problema, quando la FIFO è piena gli altri byte
>vengono scartati. Ma intato ti sei riempito la FIFO con byte inutili e,
>magari, quando arriva il frame per te il processo che snocciola i dati
>della FIFO non è stato ancora chiamato (immagina che S1 abbia processi
>"lenti", mentre S2 è velocissimo a rispondere) e così perdi il tuo frame.

No, se usi il classico approccio <STX>(02) AAAA-DDDDDD-<ETX> CRC non hai di
questi problemi.

Alla ricezione di un STX azzeri il buffer sulla periferica, e se il successivo
indirizzo non ti riguarda puoi semplicemente ingnorare il resto.

Si usano solo caratteri ASCII e i caratteri di controllo tipici
STX(02), ETX(03), ACK, ENQ, ecc.

>Tu dici che ogni tanto può capitare, tanto ci sono le ritrasmissioni...
>però, se la rete è fatta in un certo modo, questi eventi capitano
>deterministicamente.
>
>Immagina il master M, lo slave S1 e lo slave S2. Rete a 9600bps
>(8,n,1). S1 gestisce pacchetti massimi di 10 byte, quindi ha un buffer
>di 10 byte.
> - All'istante 0 S1 entra in un processo bloccante P che dura 100ms
> - Subito dopo, M invia 30 byte (31ms) a S2
> - All'istante 35ms, S2 risponde con 10 byte (10ms)
> - All'istante 35+10=45ms, M riceve tutta la risposta da S2
> - All'istante 50ms, M invia 10 byte (10ms) a S1
> - All'istante 50+10=60ms, S2 è ancora nel processo P e la FIFO
> è piena e il "suo" frame è stato perso

Per processo bloccante intendi che il µC non può nemmeno rispondere ad un
interrupt dalla UART?
Non mi sono mai trovato in questa situazione perchè se prevedo la RS485
l'hardware deve sempre essere dimensionato per supportarla pienamente.

In qualche caso dove ci potevano essere delle criticità è stato aggiunto un
AtTiny2313 o Tiny4313 solo per gestire la comunicazione seriale e ridurre i
compiti alla CPU principale.


--
ciao
Stefano

pozz

unread,
Jun 1, 2013, 9:10:14 AM6/1/13
to
Il 01/06/2013 11:56, Marco Trapanese ha scritto:
> Il 31/05/2013 23:37, pozz ha scritto:
>
>> 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?
>
> Se fosse indirizzato al micretto sarebbe lungo al massimo 30 byte. Non
> vedo il problema.

Tu scrivevi:

> 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.

Stai cioè proponendo di memorizzare nella FIFO l'intero messaggio e solo
*dopo* aver ricevuto *tutti* i byte, controllare CRC e destinatario e
quindi scartare quello che non è per me.

pozz

unread,
Jun 1, 2013, 9:14:48 AM6/1/13
to
Il 01/06/2013 12:52, SB ha scritto:
> Il giorno Fri, 31 May 2013 23:53:57 +0200, pozz <pozz...@gmail.com> ha scritto:
>>
>> Magari mi sbaglio, ma IMHO non è detto che funzioni! Attenzione, è il
>> classico approccio che avrei usato io, ma poi mi sono messo a pensare...
>>
>> Per quello che hai detto, lo slave S1 che gestisce al massimo pacchetti
>> di lunghezza massima di 10 byte, avrà un buffer di 10 byte, giusto? Ma
>> in una rete half-duplex tutti vedono tutto, quindi quello slave S1
>> vedrà/riceverà anche il frame da 100 byte diretto allo slave S2.
>>
>> Tu dici che non è un problema, quando la FIFO è piena gli altri byte
>> vengono scartati. Ma intato ti sei riempito la FIFO con byte inutili e,
>> magari, quando arriva il frame per te il processo che snocciola i dati
>> della FIFO non è stato ancora chiamato (immagina che S1 abbia processi
>> "lenti", mentre S2 è velocissimo a rispondere) e così perdi il tuo frame.
>
> No, se usi il classico approccio <STX>(02) AAAA-DDDDDD-<ETX> CRC non hai di
> questi problemi.
>
> Alla ricezione di un STX azzeri il buffer sulla periferica, e se il successivo
> indirizzo non ti riguarda puoi semplicemente ingnorare il resto.
>
> Si usano solo caratteri ASCII e i caratteri di controllo tipici
> STX(02), ETX(03), ACK, ENQ, ecc.

Sì sì, è quello che proponevo io.
Francesco, invece, proponeva di salvare nell'ISR tutti i byte ricevuti
nella memoria, *senza* guardare l'indirizzo (o meglio, guardarlo sopo
dopo che è arrivato tutto nel processo di elaborazione).


>> Tu dici che ogni tanto può capitare, tanto ci sono le ritrasmissioni...
>> però, se la rete è fatta in un certo modo, questi eventi capitano
>> deterministicamente.
>>
>> Immagina il master M, lo slave S1 e lo slave S2. Rete a 9600bps
>> (8,n,1). S1 gestisce pacchetti massimi di 10 byte, quindi ha un buffer
>> di 10 byte.
>> - All'istante 0 S1 entra in un processo bloccante P che dura 100ms
>> - Subito dopo, M invia 30 byte (31ms) a S2
>> - All'istante 35ms, S2 risponde con 10 byte (10ms)
>> - All'istante 35+10=45ms, M riceve tutta la risposta da S2
>> - All'istante 50ms, M invia 10 byte (10ms) a S1
>> - All'istante 50+10=60ms, S2 è ancora nel processo P e la FIFO
>> è piena e il "suo" frame è stato perso
>
> Per processo bloccante intendi che il µC non può nemmeno rispondere ad un
> interrupt dalla UART?

No, è chiaro che l'interrupt di ricezione è sempre abilitato e quindi
tutti i byte vengono salvati. Con processo bloccante volevo dire che
non era possibile elaborare il pacchetto ricevuto (quindi liberare la
FIFO, nel caso di pacchetto destinato ad altri) prima di uscire dalla
funzione.

Sempre supponendo di non fare alcun controllo sulla destinazione nell'ISR.

Marco Trapanese

unread,
Jun 1, 2013, 10:06:26 AM6/1/13
to
Il 01/06/2013 15:10, pozz ha scritto:

> Tu scrivevi:
> > 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.
>
> Stai cioè proponendo di memorizzare nella FIFO l'intero messaggio e solo
> *dopo* aver ricevuto *tutti* i byte, controllare CRC e destinatario e
> quindi scartare quello che non è per me.


In risposta al tuo esempio in cui comparivano solo messaggi di max 30
byte. Se passano anche messaggi più lunghi può banalmente valere il
filtro sulla lunghezza di cui sopra.

Marco


Deh!

unread,
Jun 1, 2013, 11:06:48 AM6/1/13
to
Non potresti fare un controllo sul numero di byte ricevuto oppure,
meglio ancora, un buffer ciclico nel quale eventuali messaggi non
destinati al micro piccolo, vengono automaticamente scartati dalla
funzione di scrittura in buffer?
ciao
Angelo

Claudio_F

unread,
Jun 1, 2013, 4:57:19 PM6/1/13
to
Il 01/06/2013 00:20, pozz ha scritto:
[.....]
> Sì lo so, è un periodo in cui non so cos'altro fare :-)


C'era una volta lo SNAP (Scaleable node Addres Protocol), non ritrovo
più il pdf, ma un link riassuntivo c'è ancora:
<http://www.mp3lyricsync.com/giorgio/EletDigitale/Tesina_PIC/Capitolo%202.html>

Il bello era proprio la coesistenza pacifica tra nodi ad alta capacità
di calcolo e ciofeche.

rtos

unread,
Jun 2, 2013, 6:06:02 AM6/2/13
to
Il 01/06/2013 00:20, pozz ha scritto:
> Certamente, però potrei trovare un protocollo che massimizzi il
> throughput a parità di capacità della rete, minimizzando le risorse dei
> singoli nodi.
>
> In altre parole, se ho una RS485 a 9600bps, l'ideale sarebbe poter
> inviare dati a quella velocità. Se, però, il protocollo, per come è
> definito, deve prevedere delle pause o dei feedback/ack, il throughput
> diminuisce.
Mi pare una questione di lana caprina: il thoughput di dati ha senso
in funzione dell' applicazione . Se parli di frame che devono
essere trasmessi in real-time in modo sincrono, posso anche capire,
se parli di una rete di sensori, magari di temperature o altri
parametri che magari variano a tempi biblici, non ha senso.

> Un po' come per Ethernet. Ho un canale a 100Mbps (per esempio) e cerco
> di fare in modo di massimizzare il throughput, indipendemente se
> l'applicazione è un VoIP, uno streaming, un web browsing o chissà
> cos'altro.
Affatto. Devo solo garantire che la banda a disposizione sia
sufficiente per la mia applicazione. E' accettabilissimo avere
una banda sottoutilizzata se economicamente sostenibile.

>
> Ma anche in questo caso, a livello di progetto, il protocollo *deve*
> specificare altro per poter funzionare. E cioè deve dire come risolve
> il problema del controllo di flusso.
Se il protocollo e' master-slave, il controllo del flusso e' garantito
dalla risposta dello slave indirizzato. Eventuali anomalie sono gestite
da timeout sulla risposta (e si, non si puo' fare altrimenti :-)
>
> Non è pensabile che il master invii in continuazione pacchetti ad uno
> stesso slave alla massima velocità (la larghezza di banda del canale
> fisico della rete), altrimenti lo slave, prima o poi, inizierà a perdere
> dati per FIFO full.
Ovviamente una query deve tenere conto della tipologia di slave
usati, inoltre se e' un master, non avrà un solo slave da pollare e
anche se ne avesse solo uno, ha senso fare polling alla frequenza
effettiva di produzione dati dello slave :-)

>
> Una possibilità è quella di prevedere sempre una risposta ad ogni
> pacchetto di "andata". In pratica la risposta, oltre a darmi
> eventualmente dati utili, mi darebbe l'ok ad inviare il successivo
> pacchetto. Appunto il controllo di flusso.
:-)
>
> Ma così escludo la possibilità dei pacchetti broadcast che non hanno
> risposta. E se voglio i broadcast? Allora non posso fidarmi della
> risposta per avere l'ok per la successiva trasmissione. E allora come
> fare?
un broadcast su una rete half-duplex si fa normalmente prevedendo che
il pacchetto broadcast non sia confermato (tipo UDP) da nessuno.
Se prevedi che le operazioni di broadcast necessitino di tempo per
concludersi, allora inserici un tempo di inibizione.
E comunque lo slave eventualmente interrogato in 'anticipo' puo'
semplicemente ignorare il frame ricevuto ed eventualmente ritornare
un messaggio di busy :-)

>
> Sì lo so, è un periodo in cui non so cos'altro fare :-)
>
Perche' diavolo complicarsi la vita ? vedi su.
Se ti servono messaggi broadcast *confermati* , siamo fuori strada
(non e' che non si possa fara, ma non non ne vale la pena)
SE ti servono, cambia media e invece del 485 usa il CAN, che si trova
anche in micretti da 0.8€

aa

pozz

unread,
Jun 2, 2013, 10:13:51 AM6/2/13
to
Il 01/06/2013 22:57, Claudio_F ha scritto:
> C'era una volta lo SNAP (Scaleable node Addres Protocol), non ritrovo
> più il pdf, ma un link riassuntivo c'è ancora:
> <http://www.mp3lyricsync.com/giorgio/EletDigitale/Tesina_PIC/Capitolo%202.html>
>
> Il bello era proprio la coesistenza pacifica tra nodi ad alta capacità
> di calcolo e ciofeche.

Ho recuperato il PDF delle specifiche del protocollo. E' interessante,
anche se non spiega precisamente come fa un micretto a gestire
pacchettoni (probabilmente come abbiamo già detto numerose volte, è
implicito che guardi l'header e ignori i pacchetti che non sono per lui).

Parla di un byte di sincronismo con cui inizia ogni pacchetto, ma non ho
capito come fa per evitare che capiti nel payload. Forse con il
preambolo, ma anche quello può capitare all'interno dei dati.

COmunque ha qualche spunto interessante.

Claudio_F

unread,
Jun 2, 2013, 11:50:54 AM6/2/13
to
Il 02/06/2013 16:13, pozz ha scritto:
> Ho recuperato il PDF delle specifiche del protocollo. E' interessante,
> anche se non spiega precisamente come fa un micretto a gestire
> pacchettoni (probabilmente come abbiamo già detto numerose volte, è
> implicito che guardi l'header e ignori i pacchetti che non sono per lui).

Direi di si. Tra l'altro non sarebbe neppure indispensabile che il
micretto riceva/gestisca tutti i pacchetti, ma che, a seconda del
contesto, stia in ascolto solo in momenti sensati in base allo stato del
dialogo con il corrispondente (tanto quello che si dicono gli altri nel
frattempo potrebbe non interessare)....

> Parla di un byte di sincronismo con cui inizia ogni pacchetto, ma non ho
> capito come fa per evitare che capiti nel payload. Forse con il
> preambolo, ma anche quello può capitare all'interno dei dati.

...e questo porta al problema del sync, che viene ridotto con sistemi
probabilistici (preamboli, toggle bit/bytes, timeout ecc) ma non da mai
la certezza del 100% di agganciarsi al primo colpo... a meno di usare
bit stuffing come nell'X25, operazione indolore in una trasmissione bit
oriented, molto più incasinata in una trasmissione byte oriented.

Francesco Sacchi

unread,
Jun 3, 2013, 5:49:46 AM6/3/13
to
Il 31/05/2013 23:53, pozz ha scritto:
> Il 31/05/2013 17:08, Francesco Sacchi ha scritto:
>> Il 31/05/2013 15:59, pozz ha scritto:
>>> Voi vi fate tutti sti problemi?
>>
>> Sinceramente, no, non capisco il problema.
>>
>> Ti dico come faccio di solito io.
>>
>> Sotto ISR metto i caratteri in una fifo lunga al massimo quando il
>> massimo pacchetto che voglio gestire.
>>
>> Se la fifo ᅵ piena, i caratteri successivi li butto via.
>>
>> Poi c'ᅵ un processo da qualche parte che snocciola i dati dalla fifo e
>> controlla per i vari STX, ETX, CRC e indirizzo di destinazione.
>>
>> Se il pacchetto contiene l'indirizzo dello slave lo processo, altrimenti
>> no.
>>
>> Puᅵ succedere che lo slave perda qualche pacchetto perchᅵ intasato da
>> quello che passa sulla rete, ma come dicevi tu il master ᅵ piᅵ furbo e
>> puᅵ effettuare una ritrasmissione se non riceve risposta.
>>
>> Cosa c'ᅵ che non va in questo approccio?
>
> Magari mi sbaglio, ma IMHO non ᅵ detto che funzioni! Attenzione, ᅵ il
> classico approccio che avrei usato io, ma poi mi sono messo a pensare...
>
> Per quello che hai detto, lo slave S1 che gestisce al massimo pacchetti
> di lunghezza massima di 10 byte, avrᅵ un buffer di 10 byte, giusto? Ma
> in una rete half-duplex tutti vedono tutto, quindi quello slave S1
> vedrᅵ/riceverᅵ anche il frame da 100 byte diretto allo slave S2.
>
> Tu dici che non ᅵ un problema, quando la FIFO ᅵ piena gli altri byte
> vengono scartati. Ma intato ti sei riempito la FIFO con byte inutili e,
> magari, quando arriva il frame per te il processo che snocciola i dati
> della FIFO non ᅵ stato ancora chiamato (immagina che S1 abbia processi
> "lenti", mentre S2 ᅵ velocissimo a rispondere) e cosᅵ perdi il tuo frame.
>
> Tu dici che ogni tanto puᅵ capitare, tanto ci sono le ritrasmissioni...
> perᅵ, se la rete ᅵ fatta in un certo modo, questi eventi capitano
> deterministicamente.
>
> Immagina il master M, lo slave S1 e lo slave S2. Rete a 9600bps
> (8,n,1). S1 gestisce pacchetti massimi di 10 byte, quindi ha un buffer
> di 10 byte.
> - All'istante 0 S1 entra in un processo bloccante P che dura 100ms
> - Subito dopo, M invia 30 byte (31ms) a S2
> - All'istante 35ms, S2 risponde con 10 byte (10ms)
> - All'istante 35+10=45ms, M riceve tutta la risposta da S2
> - All'istante 50ms, M invia 10 byte (10ms) a S1
> - All'istante 50+10=60ms, S2 ᅵ ancora nel processo P e la FIFO
> ᅵ piena e il "suo" frame ᅵ stato perso
>
> Forse questa sequenza "sfigata" di eventi non capita praticamente mai,
> perchᅵ gli slave sono tutti uguali (sia come micro che come firmware).
> Perᅵ non ᅵ sempre cosᅵ.
>
> Poi il master potrebbe prendere il respiro prima di iniziare una nuova
> transazione sulla rete, ma per massimizzare il thoughput sarebbe meglio
> che non lo facesse.

Il primo passo da fare ᅵ non avere processi bloccanti, per esempio
usando un kernel, anche cooperativo. Quando un processo ᅵ in attesa di
I/O deve essere switchato di contesto. Questo ᅵ importante piᅵ che fare
le cose sotto IRQ (che ᅵ peggio, perchᅵ occupi CPU inutilmente e
potresti perdere altri IRQ).

Una volta che hai ridotto la latenza media la maggior parte dei problemi
sono risolti. Per quelle poche volte che lo slave non risponderᅵ, ᅵ
comunque prevista la ritrasmissione da parte del master, per cui non ci
sono problemi.


Ciao


Marco Trapanese

unread,
Jun 3, 2013, 5:51:30 AM6/3/13
to
Il 03/06/2013 11:49, Francesco Sacchi ha scritto:

> Il primo passo da fare ᅵ non avere processi bloccanti, per esempio
> usando un kernel, anche cooperativo.


Su un micro che fa fatica ad allocare 50 byte in RAM? :)

Marco


Francesco Sacchi

unread,
Jun 3, 2013, 6:07:32 AM6/3/13
to
Certo, perchᅵ no, immagino che farᅵ poche cose e lo spazio in RAM
scalerᅵ di conseguenza.

pozz

unread,
Jun 3, 2013, 5:47:53 PM6/3/13
to
Il 03/06/2013 11:49, Francesco Sacchi ha scritto:
>
> Il primo passo da fare ᅵ non avere processi bloccanti, per esempio
> usando un kernel, anche cooperativo. Quando un processo ᅵ in attesa di
> I/O deve essere switchato di contesto. Questo ᅵ importante piᅵ che fare
> le cose sotto IRQ (che ᅵ peggio, perchᅵ occupi CPU inutilmente e
> potresti perdere altri IRQ).

Forse il termine bloccante ᅵ stato infelice. La maggior parte dei
processi/task vengono richiamati nel main loop/scheduler ad una
frequenza fissa o in presenza di eventi. Tali processi/task hanno una
loro durata fisiologica, indipendentemente che siano bloccanti sugli I/O
oppure no. E il momento in cui vengono eseguiti ᅵ assolutamente casuale
rispetto ai pacchetti che arrivano dalla rete.

Io ho fatto l'esempio di una routine che dura 100ms in S1 ed un S2 che
risponde in soli 5ms. Se vuoi possiamo scalare tutto ad una funzione di
S1 che dura 10ms e a tempi di risposta di S2 di 1ms.


> Una volta che hai ridotto la latenza media la maggior parte dei problemi
> sono risolti. Per quelle poche volte che lo slave non risponderᅵ, ᅵ
> comunque prevista la ritrasmissione da parte del master, per cui non ci
> sono problemi.

E' vero, se ho funzioni brevissime la probabilitᅵ di incappare nella mia
sequenza sfigata si abbassa... ma non ᅵ nulla. E' proprio cosᅵ che si
definiscono seriamente i protocolli di rete, andando avanti a probabilitᅵ?

Una cosa ᅵ prevedere le ritrasmissioni per far fronte ad errori di
comunicazione che hanno tipicamente un comportamento aleatorio (disturbi
elettromagnetici, ...) ed una cosa ᅵ utilizzare le ritrasmissioni per
risolvere problemi di protocollo che possono essere previsti a tavolino
e magari risolti con un'altra strategia.

Piᅵ ci penso e piᅵ mi convinco che per risolvere a priori in modo
deterministico la mia sequenza sfigata, bisogna evitare che uno slave
memorizzi i pacchetti destinati ad altri (e per questo ᅵ necessario fare
una minima decodifica del pacchetto nell'ISR di ricezione) oppure
salomonicamente impedire al master di iniziare una nuova transazione
(domanda/risposta) sulla rete prima che sia passato un buon timeout
(500ms?) dall'ultima risposta.

SB

unread,
Jun 4, 2013, 8:33:19 AM6/4/13
to
Il giorno Mon, 03 Jun 2013 23:47:53 +0200, pozz <pozz...@gmail.com> ha scritto:

>
>Pi� ci penso e pi� mi convinco che per risolvere a priori in modo
>deterministico la mia sequenza sfigata, bisogna evitare che uno slave
>memorizzi i pacchetti destinati ad altri (e per questo � necessario fare
>una minima decodifica del pacchetto nell'ISR di ricezione) oppure
>salomonicamente impedire al master di iniziare una nuova transazione
>(domanda/risposta) sulla rete prima che sia passato un buon timeout
>(500ms?) dall'ultima risposta.

Nelle applicazioni con la RS485 usiamo ambedue le cose che hai detto, solo il
timeout � pi� breve (300 mS), ma � un problema da poco, nei log che monitorano
la comunicazione la ritrasmissioni sono praticamente sempre zero, e ci sono
anche tratte abbastanza lunghe (+ di 500m).

Abbiamo optoisolato, ma questi sono altri problemi, il protocollo non c'entra.


--
ciao
Stefano

Francesco Sacchi

unread,
Jun 4, 2013, 2:02:18 PM6/4/13
to
Il 03/06/2013 23:47, pozz ha scritto:
> Il 03/06/2013 11:49, Francesco Sacchi ha scritto:
> >
>> Il primo passo da fare ᅵ non avere processi bloccanti, per esempio
>> usando un kernel, anche cooperativo. Quando un processo ᅵ in attesa di
>> I/O deve essere switchato di contesto. Questo ᅵ importante piᅵ che fare
>> le cose sotto IRQ (che ᅵ peggio, perchᅵ occupi CPU inutilmente e
>> potresti perdere altri IRQ).
>
> Forse il termine bloccante ᅵ stato infelice. La maggior parte dei
> processi/task vengono richiamati nel main loop/scheduler ad una
> frequenza fissa o in presenza di eventi. Tali processi/task hanno una
> loro durata fisiologica, indipendentemente che siano bloccanti sugli I/O
> oppure no. E il momento in cui vengono eseguiti ᅵ assolutamente casuale
> rispetto ai pacchetti che arrivano dalla rete.

Se hai uno scheduler sincrono, come mi sembra di capire, i task sono
bloccanti sull'I/O per definizione. Se hai un task che dura 100ms o
anche solo 10, in un sistema embedded significa che ti blocchi sull'I/O;
ᅵ difficile avere compiti CPU intensive in un'applicazione come la tua.

Quello che voglio dire ᅵ che la banda che ᅵ in grado di processare un
micretto tipico ᅵ di molto superiore a quella in arrivo da una seriale a
9600 bps. Il problema ᅵ la latenza. Se si abbassa il jitter sulla
latenza con cui si gestiscono i processi non ci sono problemi. La FIFO
riempita sotto interrupt va dimensionata in modo da gestire la latenza
nel caso peggiore, e teoricamente potrebbe anche essere inferiore alla
massima lunghezza del pacchetto che il micro puᅵ ricevere.

Tutta l'elaborazione la fai poi off-line in un altro processo.

>> Una volta che hai ridotto la latenza media la maggior parte dei problemi
>> sono risolti. Per quelle poche volte che lo slave non risponderᅵ, ᅵ
>> comunque prevista la ritrasmissione da parte del master, per cui non ci
>> sono problemi.
>
> E' vero, se ho funzioni brevissime la probabilitᅵ di incappare nella mia
> sequenza sfigata si abbassa... ma non ᅵ nulla. E' proprio cosᅵ che si
> definiscono seriamente i protocolli di rete, andando avanti a probabilitᅵ?
>
> Una cosa ᅵ prevedere le ritrasmissioni per far fronte ad errori di
> comunicazione che hanno tipicamente un comportamento aleatorio (disturbi
> elettromagnetici, ...) ed una cosa ᅵ utilizzare le ritrasmissioni per
> risolvere problemi di protocollo che possono essere previsti a tavolino
> e magari risolti con un'altra strategia.

> Piᅵ ci penso e piᅵ mi convinco che per risolvere a priori in modo
> deterministico la mia sequenza sfigata, bisogna evitare che uno slave
> memorizzi i pacchetti destinati ad altri (e per questo ᅵ necessario fare
> una minima decodifica del pacchetto nell'ISR di ricezione) oppure
> salomonicamente impedire al master di iniziare una nuova transazione
> (domanda/risposta) sulla rete prima che sia passato un buon timeout
> (500ms?) dall'ultima risposta.

Secondo il mio modesto parere stai cercano di risolvere un problema nel
livello sbagliato. Determinare la lunghezza del buffer a priori ᅵ
impossibile e la soluzione di fare controlli nella ISR va nella
direzione sbagliata (aumento del jitter sulla latenza).

Ciao!



pozz

unread,
Jun 4, 2013, 5:43:53 PM6/4/13
to
Il 04/06/2013 20:02, Francesco Sacchi ha scritto:
> Il 03/06/2013 23:47, pozz ha scritto:
>>>
>>> Il primo passo da fare ᅵ non avere processi bloccanti, per esempio
>>> usando un kernel, anche cooperativo. Quando un processo ᅵ in attesa di
>>> I/O deve essere switchato di contesto. Questo ᅵ importante piᅵ che fare
>>> le cose sotto IRQ (che ᅵ peggio, perchᅵ occupi CPU inutilmente e
>>> potresti perdere altri IRQ).
>>
>> Forse il termine bloccante ᅵ stato infelice. La maggior parte dei
>> processi/task vengono richiamati nel main loop/scheduler ad una
>> frequenza fissa o in presenza di eventi. Tali processi/task hanno una
>> loro durata fisiologica, indipendentemente che siano bloccanti sugli I/O
>> oppure no. E il momento in cui vengono eseguiti ᅵ assolutamente casuale
>> rispetto ai pacchetti che arrivano dalla rete.
>
> Se hai uno scheduler sincrono, come mi sembra di capire, i task sono
> bloccanti sull'I/O per definizione. Se hai un task che dura 100ms o
> anche solo 10, in un sistema embedded significa che ti blocchi sull'I/O;
> ᅵ difficile avere compiti CPU intensive in un'applicazione come la tua.

A parte calcoli in virgola mobile che ho notato essere molto CPU
intensive, in effetti hai ragione, i task piᅵ lunghi sono quelli legati
agli I/O: scrittura di un display, I2C/SPI master implementato software,
ecc.

Perᅵ, in molti casi, la vedo veramente dura cercare di "spezzare" il
task per evitare che duri troppo. Magari tu hai piᅵ esperienza in
questo senso, ma a me risulta difficile.

Esempio: proprio recentemente mi ᅵ capitato di dover leggere un codice
Manchester in uscita da un lettore RFID (U2270B della ex Temic, oggi
Atmel). Il compito non ᅵ semplice: devi sincronizzarti con i fronti del
segnale, misurare dei tempi in modo abbastanza preciso e cose simili.
L'hw me lo sono ritrovato e non ho potuto utilizzare nessuna periferica
hw utile (contatore di impulsi o capture, interrupt on pin change, ...),
quindi implementazione completamente sw. Alla fine, tra ricerca del
preambolo di sincronismo e decodifica dei 64 bit del codice ad un
bitrate di 125kHz/64, il task mi dura circa 100ms. E non mi sembra
facilmente interrompibile, anche se per molto tempo sto aspettando
fronti o timeout.

Altro esempio: I2C master bitbang. Devo ricostruire la forma d'onda I2C
con "metti pin alto", "aspetta il tempo di bit", "metti il pin basso",
ecc. Se devo leggere 50 byte da una EEPROM I2C, il tempo se ne va.


> Quello che voglio dire ᅵ che la banda che ᅵ in grado di processare un
> micretto tipico ᅵ di molto superiore a quella in arrivo da una seriale a
> 9600 bps. Il problema ᅵ la latenza. Se si abbassa il jitter sulla
> latenza con cui si gestiscono i processi non ci sono problemi. La FIFO
> riempita sotto interrupt va dimensionata in modo da gestire la latenza
> nel caso peggiore, e teoricamente potrebbe anche essere inferiore alla
> massima lunghezza del pacchetto che il micro puᅵ ricevere.
>
> Tutta l'elaborazione la fai poi off-line in un altro processo.

Forse ho capito il tuo concetto: se il processo che gestisce i pacchetti
viene richiamato nel caso peggiore entro T dall'ultima chiamata (ᅵ
quello che tu forse chiami latenza), ᅵ sufficiente garantire un buffer
che tenga almeno

T / (10 / B)

dove B ᅵ il baudrate (bps) e 10 sono i bit per simbolo (start, 8 bit di
dati e stop).

Se riesco a fare dei processi molto snelli che mi permettono di avere un
valore di T massimo di 10ms a 9600bps, dovrei avere un buffer di soli 10
byte, che salgono perᅵ a piᅵ di 100 a 115.2kbps.

IMHO questo approccio puᅵ essere implementato se riesci a fare uno
studio serio della latenza e del jitter, ma nella pratica per me risulta
*molto* complicata.
Un modo per misurare il ritardo tra due chiamate successive del processo
che gestisce la rete ᅵ quello di visualizzarlo su un oscilloscopio
tramite pin. Abilito la persistenza infinita e dopo un po' di tempo
vado a vedere il ritardo massimo.
Il problema ᅵ che questo ritardo dipende spesso dalle condizioni d'uso.
Per esempio, se c'ᅵ un display e tasti e lo uso, in quel momento la
latenza potrebbe aumentare.

Probabilmente il metodo piᅵ preciso per valutare T non ᅵ misurarlo, ma
calcolarlo... auguri! E' un po' come calcolare a priori la dimensione
minima dello stack... mai riuscito a fare una cosa del genere.

Quindi il tuo metodo della FIFO sufficientemente grande che memorizza
*tutti* i pacchetti in circolazione ᅵ fattibile se puoi allocare
centinaia di byte senza problemi e se hai processi molto brevi. In
questo caso, puoi evitare di far di conto ed essere quasi sicuro di non
avere problemi di ritrasmissioni.

L'altro metodo (quello di scartare nell'ISR i pacchetti destinati ad
altri) ti evita queste misure/calcoli complicati e ti dᅵ la certezza di
non avere problemi. La dimensione della FIFO ᅵ sufficiente che sia
esattamente uguale a quella del pacchetto massimo da noi gestito. Poi
la latenza del processo che gestisce i pacchetti potrebbe essere anche
elevata (naturalmente elevato sarᅵ il tempo di risposta).

CortexA57

unread,
Jun 5, 2013, 2:13:28 AM6/5/13
to
> L'altro metodo (quello di scartare nell'ISR i pacchetti destinati ad
> altri) ti evita queste misure/calcoli complicati e ti dà la certezza di
> non avere problemi. La dimensione della FIFO è sufficiente che sia
> esattamente uguale a quella del pacchetto massimo da noi gestito. Poi
> la latenza del processo che gestisce i pacchetti potrebbe essere anche
> elevata (naturalmente elevato sarà il tempo di risposta).
No, per scartare un pacchetto non e' necessario mememorizzarlo tutto,
anzi! Un protocollo e' una macchina a stati, per cui banalmente quando
riconosci che il pacchetto non e' per te', gli N byte a seguire sarano
scatati ( se e' previsto un header con lunghezza).
Se il protocollo prevede un STX univoco, bastera' tornare allo stato di
attesa STX, se no si scartano i byte del pacchetto.
Eventualmente va gestito un timeout di frame per essere sicuri di
non rimanere appesi in caso di perdita di caratteri.
AA.




pozz

unread,
Jun 5, 2013, 6:30:45 AM6/5/13
to
On Jun 5, 8:13 am, CortexA57 <Cortex...@ch.invalid> wrote:
> > L'altro metodo (quello di scartare nell'ISR i pacchetti destinati ad
> > altri) ti evita queste misure/calcoli complicati e ti d la certezza di
> > non avere problemi.  La dimensione della FIFO sufficiente che sia
> > esattamente uguale a quella del pacchetto massimo da noi gestito.  Poi
> > la latenza del processo che gestisce i pacchetti potrebbe essere anche
> > elevata (naturalmente elevato sar il tempo di risposta).
>
> No, per scartare un pacchetto non e' necessario mememorizzarlo tutto,
> anzi! Un protocollo e' una macchina a stati, per cui banalmente quando
> riconosci che il pacchetto non e' per te', gli N byte a seguire sarano
> scatati ( se e' previsto un header con lunghezza).
> Se il protocollo prevede un STX univoco, bastera' tornare allo stato di
> attesa STX, se no si scartano i byte del pacchetto.
> Eventualmente va gestito un timeout di frame per essere sicuri di
> non rimanere appesi in caso di perdita di caratteri.

Sì, è esattamente quello che volevo dire io quando scrivevo "scartare
nell'ISR i pacchetti destinati ad altri". Cioè nell'ISR ho una
semplice macchina
a stati che mi dice se sono in attesa di un nuovo pacchetto, se sto
ricevendo
un pacchetto per me (quindi da memorizzare) oppure sto ricevendo un
pacchetto per altri (quindi da scartare).

Francesco puntava sul fatto che una implementazione semplice che
memorizza senza filtri tutti i byte di tutti pacchetti (per me e per
altri)
in una FIFO è più che sufficiente.

Francesco Sacchi

unread,
Jun 5, 2013, 11:25:14 AM6/5/13
to
Il 04/06/2013 23:43, pozz ha scritto:
> Il 04/06/2013 20:02, Francesco Sacchi ha scritto:
>> Il 03/06/2013 23:47, pozz ha scritto:
>>>>
>>>> Il primo passo da fare è non avere processi bloccanti, per esempio
>>>> usando un kernel, anche cooperativo. Quando un processo è in attesa di
>>>> I/O deve essere switchato di contesto. Questo è importante più che fare
>>>> le cose sotto IRQ (che è peggio, perché occupi CPU inutilmente e
>>>> potresti perdere altri IRQ).
>>>
>>> Forse il termine bloccante è stato infelice. La maggior parte dei
>>> processi/task vengono richiamati nel main loop/scheduler ad una
>>> frequenza fissa o in presenza di eventi. Tali processi/task hanno una
>>> loro durata fisiologica, indipendentemente che siano bloccanti sugli I/O
>>> oppure no. E il momento in cui vengono eseguiti è assolutamente casuale
>>> rispetto ai pacchetti che arrivano dalla rete.
>>
>> Se hai uno scheduler sincrono, come mi sembra di capire, i task sono
>> bloccanti sull'I/O per definizione. Se hai un task che dura 100ms o
>> anche solo 10, in un sistema embedded significa che ti blocchi sull'I/O;
>> è difficile avere compiti CPU intensive in un'applicazione come la tua.
>
> A parte calcoli in virgola mobile che ho notato essere molto CPU
> intensive, in effetti hai ragione, i task più lunghi sono quelli legati
> agli I/O: scrittura di un display, I2C/SPI master implementato software,
> ecc.
>
> Però, in molti casi, la vedo veramente dura cercare di "spezzare" il
> task per evitare che duri troppo. Magari tu hai più esperienza in
> questo senso, ma a me risulta difficile.
>
> Esempio: proprio recentemente mi è capitato di dover leggere un codice
> Manchester in uscita da un lettore RFID (U2270B della ex Temic, oggi
> Atmel). Il compito non è semplice: devi sincronizzarti con i fronti del
> segnale, misurare dei tempi in modo abbastanza preciso e cose simili.
> L'hw me lo sono ritrovato e non ho potuto utilizzare nessuna periferica
> hw utile (contatore di impulsi o capture, interrupt on pin change, ...),
> quindi implementazione completamente sw. Alla fine, tra ricerca del
> preambolo di sincronismo e decodifica dei 64 bit del codice ad un
> bitrate di 125kHz/64, il task mi dura circa 100ms. E non mi sembra
> facilmente interrompibile, anche se per molto tempo sto aspettando
> fronti o timeout.
>
> Altro esempio: I2C master bitbang. Devo ricostruire la forma d'onda I2C
> con "metti pin alto", "aspetta il tempo di bit", "metti il pin basso",
> ecc. Se devo leggere 50 byte da una EEPROM I2C, il tempo se ne va.

E' proprio questo a cui mi riferisco quando dico che non ci devono
essere compiti bloccanti.
Quando devi attendere, invece di far aspettare la CPU ferma a non fare
nulla, con un kernel si passa a fare altro, e si ritorna quando è
passato il tempo di attesa. In compiti come quelli che hai indicato
sopra, l'utilizzo di CPU è veramente minimo ed è un peccato sprecarla
per attendere il fronte o il momento giusto.

>> Quello che voglio dire è che la banda che è in grado di processare un
>> micretto tipico è di molto superiore a quella in arrivo da una seriale a
>> 9600 bps. Il problema è la latenza. Se si abbassa il jitter sulla
>> latenza con cui si gestiscono i processi non ci sono problemi. La FIFO
>> riempita sotto interrupt va dimensionata in modo da gestire la latenza
>> nel caso peggiore, e teoricamente potrebbe anche essere inferiore alla
>> massima lunghezza del pacchetto che il micro può ricevere.
>>
>> Tutta l'elaborazione la fai poi off-line in un altro processo.
>
> Forse ho capito il tuo concetto: se il processo che gestisce i pacchetti
> viene richiamato nel caso peggiore entro T dall'ultima chiamata (è
> quello che tu forse chiami latenza), è sufficiente garantire un buffer
> che tenga almeno
>
> T / (10 / B)
>
> dove B è il baudrate (bps) e 10 sono i bit per simbolo (start, 8 bit di
> dati e stop).
>
> Se riesco a fare dei processi molto snelli che mi permettono di avere un
> valore di T massimo di 10ms a 9600bps, dovrei avere un buffer di soli 10
> byte, che salgono però a più di 100 a 115.2kbps.
>
> IMHO questo approccio può essere implementato se riesci a fare uno
> studio serio della latenza e del jitter, ma nella pratica per me risulta
> *molto* complicata.

Uno studio del genere, come dici, può essere fatto solo in modo
probabilistico; questo perché non usi un kernel.

Se già ne usassi uno anche solo cooperativo, la latenza media si abbassa
di almeno un ordine di grandezza. Se poi usi un kernel preemptive hai
addirittura garanzie di real time, ovvero sei in grado di dire con
precisione e in modo predeterminato (niente prove o statistiche), con
quanta latenza il tuo processo di elaborazione dati sarà attivato. Con
un kernel preemptive, in processori tipici embedded come quelli che usi
tu, la latenza è dell'ordine dei microsecondi, quindi ci staresti
ampiamente.

pozz

unread,
Jun 6, 2013, 1:06:57 AM6/6/13
to
Il 05/06/2013 17:25, Francesco Sacchi ha scritto:
> Il 04/06/2013 23:43, pozz ha scritto:
>>
>> Perᅵ, in molti casi, la vedo veramente dura cercare di "spezzare" il
>> task per evitare che duri troppo. Magari tu hai piᅵ esperienza in
>> questo senso, ma a me risulta difficile.
>>
>> Esempio: proprio recentemente mi ᅵ capitato di dover leggere un codice
>> Manchester in uscita da un lettore RFID (U2270B della ex Temic, oggi
>> Atmel). Il compito non ᅵ semplice: devi sincronizzarti con i fronti del
>> segnale, misurare dei tempi in modo abbastanza preciso e cose simili.
>> L'hw me lo sono ritrovato e non ho potuto utilizzare nessuna periferica
>> hw utile (contatore di impulsi o capture, interrupt on pin change, ...),
>> quindi implementazione completamente sw. Alla fine, tra ricerca del
>> preambolo di sincronismo e decodifica dei 64 bit del codice ad un
>> bitrate di 125kHz/64, il task mi dura circa 100ms. E non mi sembra
>> facilmente interrompibile, anche se per molto tempo sto aspettando
>> fronti o timeout.
>>
>> Altro esempio: I2C master bitbang. Devo ricostruire la forma d'onda I2C
>> con "metti pin alto", "aspetta il tempo di bit", "metti il pin basso",
>> ecc. Se devo leggere 50 byte da una EEPROM I2C, il tempo se ne va.
>
> E' proprio questo a cui mi riferisco quando dico che non ci devono
> essere compiti bloccanti.
> Quando devi attendere, invece di far aspettare la CPU ferma a non fare
> nulla, con un kernel si passa a fare altro, e si ritorna quando ᅵ
> passato il tempo di attesa. In compiti come quelli che hai indicato
> sopra, l'utilizzo di CPU ᅵ veramente minimo ed ᅵ un peccato sprecarla
> per attendere il fronte o il momento giusto.

Per micro piccoli non mi sono mai posto il problema di un kernel: ogni
processo ᅵ chiamato, uno dopo l'altro, nel main loop. Ma anche un
kernel, in alcune situazioni, non potrebbe aiutarmi.

Pensa se devi sincronizzarti su un fronte di un pin. Devi fare polling
su quel pin *senza uscire*, altrimenti rischi di ritornare nella
funzione quando il fronte ᅵ giᅵ passato da un po' e di rendere poco
accurata la sincronizzazione.

Comunque sarebbe bello poter approfondire il discorso kernel per piccoli
micro... qualche risorsa da leggere?


>>> Quello che voglio dire ᅵ che la banda che ᅵ in grado di processare un
>>> micretto tipico ᅵ di molto superiore a quella in arrivo da una seriale a
>>> 9600 bps. Il problema ᅵ la latenza. Se si abbassa il jitter sulla
>>> latenza con cui si gestiscono i processi non ci sono problemi. La FIFO
>>> riempita sotto interrupt va dimensionata in modo da gestire la latenza
>>> nel caso peggiore, e teoricamente potrebbe anche essere inferiore alla
>>> massima lunghezza del pacchetto che il micro puᅵ ricevere.
>>>
>>> Tutta l'elaborazione la fai poi off-line in un altro processo.
>>
>> Forse ho capito il tuo concetto: se il processo che gestisce i pacchetti
>> viene richiamato nel caso peggiore entro T dall'ultima chiamata (ᅵ
>> quello che tu forse chiami latenza), ᅵ sufficiente garantire un buffer
>> che tenga almeno
>>
>> T / (10 / B)
>>
>> dove B ᅵ il baudrate (bps) e 10 sono i bit per simbolo (start, 8 bit di
>> dati e stop).
>>
>> Se riesco a fare dei processi molto snelli che mi permettono di avere un
>> valore di T massimo di 10ms a 9600bps, dovrei avere un buffer di soli 10
>> byte, che salgono perᅵ a piᅵ di 100 a 115.2kbps.
>>
>> IMHO questo approccio puᅵ essere implementato se riesci a fare uno
>> studio serio della latenza e del jitter, ma nella pratica per me risulta
>> *molto* complicata.
>
> Uno studio del genere, come dici, puᅵ essere fatto solo in modo
> probabilistico; questo perchᅵ non usi un kernel.
>
> Se giᅵ ne usassi uno anche solo cooperativo, la latenza media si abbassa
> di almeno un ordine di grandezza. Se poi usi un kernel preemptive hai
> addirittura garanzie di real time, ovvero sei in grado di dire con
> precisione e in modo predeterminato (niente prove o statistiche), con
> quanta latenza il tuo processo di elaborazione dati sarᅵ attivato. Con
> un kernel preemptive, in processori tipici embedded come quelli che usi
> tu, la latenza ᅵ dell'ordine dei microsecondi, quindi ci staresti
> ampiamente.
>

Andromeda

unread,
Jun 6, 2013, 1:48:46 AM6/6/13
to
Il 06/06/2013 07:06, pozz ha scritto:

> Comunque sarebbe bello poter approfondire il discorso kernel per piccoli
> micro... qualche risorsa da leggere?


http://webhome.csc.uvic.ca/~mcheng/466/spring.2012/handouts/Technical%20References/Patterns%20For%20Time-Triggered%20Embedded%20Systems.pdf

hth


--
Mai mettersi a discutere con un idiota:
- prima ti porta al suo livello e poi ti batte con l'esperienza;
- chi ascolta potrebbe non capire la differenza.
0 new messages