Devo usare più macchine a stati per un protocollo a più livelli?

3

Quando si implementa un protocollo di comunicazione multilivello, i livelli sono comunemente implementati come macchine di stato?

Ho un'implementazione di PMBus su cui sto attualmente lavorando per un dispositivo incorporato. Ho un'interfaccia basata su interrupt per la gestione di come l'I2C utilizza il driver H / W per ricevere e trasmettere byte su e fuori da un buffer, essenzialmente serializzando i dati.

Una macchina a stati implementa quindi il livello SMBus "medio" prendendo i dati dal buffer e formando messaggi da esso in base a come il protocollo impone cosa aspettarsi per un messaggio di tipo generico, questa macchina a stati può anche aggiungere informazioni basate sull'input da linee I / O aggiuntive.

Una seconda macchina a stati quindi blocca lo stack con il livello PMBus controllando il messaggio generico come si applica a tipi specifici di messaggi, aggiungendo di nuovo alcune ulteriori informazioni dalle linee di I / O e successivamente cerca un gestore di comandi in base al messaggio e passa i dati dal messaggio.

L'intero caboodle funziona quindi al contrario per trasmettere le risposte dal gestore di comandi o richieste da altre parti del sistema (che funziona da una macchina a stati terzi) per modificare l'output sulle linee di I / O, come la registrazione di uno stato di errore che richiede una richiesta di segnale di servizio.

Vengo da uno sfondo embedded di basso livello con poca esperienza di programmazione del lavoro reale, di conseguenza ho solo una piccola idea dei modelli di progettazione previsti e accettati per problemi comuni. Quindi la mia domanda; è una tale macchina statale che mette a punto una soluzione comune o logicamente prevista per l'implementazione di protocolli stratificati?

Mi è sembrato efficace e robusto (un requisito morbido è che la funzionalità del livello sia incapsulata) quando l'ho pensato qualche tempo fa, ma ripensandoci su esso sembra che sia un po 'sovraingegnerizzato e che ci potrebbe essere un po' più semplice metodo.

EDIT: mi sono ricordato che la ragione principale per cui ho seguito questa rotta è che l'esecuzione degli strati superiori è disaccoppiata dall'interfaccia basata sull'interrupt. Questo è utile perché da un interrupt per i dati ricevuti fino al ritorno dal gestore di comandi per i dati trasmessi può (a seconda di come deve essere utilizzata l'implementazione) può costituire un tempo relativamente lungo rispetto alla logica di business principale del mio dispositivo che opera abbastanza velocemente e ha il requisito del tempo di esecuzione nel caso peggiore. Quindi la mia macchina a stati logici di business (la terza da sopra) è ciò che chiama le macchine dello stato del protocollo, dall'alto verso il basso, quando ha tempo. Ciò significa che mentre la ricezione e la trasmissione dei dati sono asincrone, l'elaborazione dei dati non è.

    
posta Toby 24.02.2015 - 11:58
fonte

2 risposte

4

Dici di avere una piccola esperienza del mondo reale in quest'area. Impara dagli esperti per diventare uno. Guardati intorno a cosa fanno i professionisti di questo settore per risolvere il tuo problema. Le implementazioni PMBus open source sono disponibili. Il kernel di Linux è un esempio. Ma Freescale ha anche una libreria PMBus là fuori che è probabilmente migliore per il tuo background.

Consigli generali su come pensare a queste cose:

Se i livelli dei protocolli sono abbastanza complessi, il layering è un ottimo modo per gestire questa complessità. Tuttavia, i livelli creano piccole mini-interfacce. Quindi non ne vuoi troppi. Ognuno di questi può scomporre le possibili ottimizzazioni o le prestazioni lente. Quindi, c'è un equilibrio da fare con la stratificazione per ridurre la complessità e le prestazioni. Ricorda che la stratificazione crea una struttura rigida attorno all'implementazione. Questa rigidità aiuta a renderlo comprensibile, ma il prezzo è che per definizione hai meno flessibilità.

Un altro modo di considerare il problema è se i livelli hanno o meno stato. In generale, gli strati senza stato sono preferiti. Molte macchine a stati interagenti possono causare problemi nel mantenerle sincronizzate l'una con l'altra. Non prenderlo troppo lontano. Ovviamente alcuni livelli hanno uno stato intrinseco (come il livello I2C hardware inferiore con un messaggio a pacchetti multipli). Ma molti strati no. Spesso, lo stato è inerente a livello di hardware e a livello di applicazione. Cerca di mantenere tutti gli strati centrali senza stato. Nel tuo caso, quei bit extra di informazioni dalle linee di I / O nello stato intermedio potrebbero essere un po 'fastidiosi.

La parte più trascurata e complessa di questi tipi di design è la gestione degli errori. All'inizio può sembrare semplice e diretto, ma poi ti rendi conto di quei piccoli casi in cui l'autobus non risponde e devi uscire da quel ciclo di attesa. Oppure il buffer è pieno e hai ricevuto dati, ecc. È qui che quelle macchine a stati interagenti possono diventare un incubo. Assicurati di guardare quei percorsi o avrai molto da fare.

    
risposta data 24.02.2015 - 14:52
fonte
1

Non conosco gli standard del settore, ma ho usato le macchine a stati in più livelli di uno stack di protocolli di comunicazione (sp il protocollo PS / 2) per gli stessi motivi che hai dato; ha funzionato abbastanza bene: mi ha permesso di coordinare e controllare tutto ciò che stava succedendo, esp. le cose guidate da interrupt.

Anche se è andato bene per me , penso che dovresti prestare attenzione ai consigli e alle avvertenze di @thepacker e @caveman, perché ci sono più overhead e complessità coinvolti nell'esecuzione e nel coordinamento di più macchine ; devi anche essere rigoroso in modo che il design non si allontani da te.

Devo anche dire che non ho dovuto mantenere lo stack - era un progetto one-off - quindi non sono sicuro di come le cose sarebbero cresciute nel tempo.

Aree problematiche che ricordo di aver avuto durante la progettazione di cose (sono passati alcuni anni e più di alcuni progetti da quando ho lavorato su questo, quindi il mio ricordo potrebbe essere inaccurato) che avrebbero dovuto comunicare le macchine dei diversi livelli - - Ho finito per usare dati statici, con funzioni accessorie, condivisi tra livelli e controllare la gestione degli errori. Alla fine il mio progetto aveva macchine in ogni strato che controllavano le macchine nello strato sottostante per la trasmissione; Ho dimenticato come fosse strutturata esattamente la ricezione, ma era una sorta di banda separata di controllo dalla trasmissione.

Come alternativa all'utilizzo di macchine a stati potresti controllare programmazione reattiva funzionale ( sembra un bel tutorial sulla programmazione reattiva ). Anche se probabilmente non sarai in grado di usarlo direttamente in un progetto integrato, potrebbe darti qualche idea su come affrontare le cose.

Se vuoi ancora utilizzare le macchine a stati, ho avuto una buona esperienza nell'implementarle in C con questo approccio:

Utilizzare 3 funzioni per definire e controllare la macchina:

// get the next state based on the current
// state and the transition input --
// this should be a pure function
static State findNextState(prevState, input);

// react to a state transition --
// side-effects go in here
static void reactToStateTransition(prevState, nextState, input);

static State currentState = INIT;

// control the machine's state and
// call the other two functions
void transitionStates(input)
{
    State prevState = currentState;
    State nextState = findNextState(prevState, input);

    if (prevState != nextState)
    {
        reactToStateTransition(prevState, nextState, input);
        currentState = nextState;
    }
}

Quindi puoi usare questo per gli stati di transizione, per esempio in un interrupt:

void isr()
{
    transitionStates(SOMETHING_HAPPENED);
}

O, meglio ancora, avere il flag di interrupt per la transizione da eseguire con codice a livello non di interruzione.

Questa struttura funziona bene per le macchine piatte di piccole e medie dimensioni, ma se ottieni molti stati con molte transizioni o, peggio ancora, macchine di stato annidate, non gestisce le cose così bene.

    
risposta data 26.02.2015 - 19:51
fonte

Leggi altre domande sui tag