Domanda:
È possibile interrompere il processo di copia di una struttura tramite un interrupt in C incorporato?
Stani
2018-09-06 14:27:06 UTC
view on stackexchange narkive permalink

All'interno del driver ho una funzione per copiare i dati dalla struttura interna in una struttura dall'applicazione.

Questo processo può essere interrotto da un trigger di interrupt del microcontrollore?

  uint16_t getRawData (struct Data * Data_external)
{
  if (Data_external == NULL)
  {
    return ERR_PARA;
  }
  altro
  {
    * Data_external = Data_internal;// il processo di copia.Potrebbe essere interrotto?
  }
  return ERR_NONE;
}
 
Non esiste davvero un "processo di copia", ci saranno istruzioni che copiano i byte e se non sono atomici possono essere interrotti, dipende dalla tua architettura, compilatore, impostazioni e allineamento
Non vi è alcuna garanzia in C che un processo di copia della struttura non possa essere interrotto.Tuttavia, di solito si suppone che l'interrupt ritorni al punto nel codice in cui il processo di copia può essere completato.Quindi probabilmente non ha importanza a meno che il codice di interrupt non dipenda da esso per qualche motivo (improbabile nella maggior parte delle circostanze). Se queste strutture fanno parte di una coppia di driver di interrupt superiore / inferiore, tuttavia, questo potrebbe essere un problema se il livello superioreè in procinto di rimuovere o aggiungere un "blocco" a un buffer quando si verifica un interrupt che deve anche far fronte a "blocchi" nello stesso buffer.
@jonk: Si prega di non rispondere alla domanda nei commenti, poiché questo ignora il normale processo di revisione delle risposte, come [discusso in meta] (https://meta.stackexchange.com/questions/117251)
@DaveTweed Allora tu e questo sito perdete *** i miei commenti.Non scrivo risposte a meno che non abbia il tempo di scriverne di più complete.È il mio unico modo di operare e non lo cambierò.Se sento di avere abbastanza tempo per una "risposta corretta" secondo la mia definizione, continuerò come prima.Ma sto lavorando molto duramente su diversi progetti attivi e NON ho il tempo per il mio solito livello di contesto e contenuto di risposta.Quindi o scrivo brevi commenti come commenti, o il sito perde qualsiasi accesso al mio tempo.La tua chiamata.Il mio tempo è dato alle mie condizioni, o per niente.
@jonk: Non c'è niente di sbagliato nello scrivere una risposta breve purché sia completa e autonoma, come lo è il tuo commento.Il tuo impegno per risposte lunghe è interamente su di te.Il sito ha regole e processi e sto solo cercando di guidarti nella giusta direzione.In definitiva, dipende interamente da te: avresti potuto ricevere 9 voti positivi (+90 ripetizioni) sulla tua risposta ...
@DaveTweed Grazie per la spinta.I punti sono per lo più irrilevanti.Penso che una volta arrivato alla "pubblicità ridotta" di 200 punti, non mi sono preoccupato del resto (né l'ho usato.) Non credo di meritare neanche i numeri alti che ho in questo momento.Sono solo un hobbista, per l'amor del cielo.E sono molto preoccupato che le persone possano scambiare quel numero di reputazione come un significato più di quanto dovrebbe per loro.Preferirei che le mie parole fossero sempre "sospette" e meritevoli di critica, non prese come una sorta di vangelo.Se potessi ridurre il numero di ripetizioni, lo farei.
@jonk Se davvero vuoi che le persone siano in grado di "sospettare" le tue risposte, per favore permetti alle persone di votarle correttamente.Nel (improbabile!) Caso in cui pubblichi qualcosa di sbagliato come commento, gli utenti non sarebbero in grado di votare.Questo può essere particolarmente un problema se le persone votano un commento che inizialmente sembra corretto (di nuovo, non che io metta in dubbio la qualità dei tuoi commenti / risposte :))
@mbrig Potresti fraintendermi.Scelgo di * solo * scrivere *** risposte *** in quanto tali e con il mio nome allegato se includono il contesto e il contenuto completi, oppure dove penso di poter fornire un approccio * insolito * o * unico *.Sono anche sempre ricercati, nel senso che non posterò una risposta prima di aver * ricontrollato * me stesso trovando riferimenti e materiale di supporto che concordano con la mia posizione e che posso anche citare, quando richiesto.Non scrivo solo.Scrivo, quindi ricerco, controllo incrociato e verifico.Quindi posta.Altrimenti, non sembra una mia risposta.
@mbrig Infine, il mio numero di rappresentante non è * significativo. * Potrebbe essere quello che scrivo.Ma questa è una questione separata.Vorrei solo poter cancellare o eliminare il mio numero di rappresentante.Sono felice che alcune persone abbiano trovato utile una mia (o due) risposta.Ma c'è una tendenza naturale per le persone a immaginare qualcos'altro dato il mio numero di ripetizioni e vorrei che non lo facessero.È tutto.Il tuo suggerimento non risponde a *** nessuna delle mie preoccupazioni.
@jonk: Potresti iniziare una domanda di taglie e premiare qualcuno con una reputazione di 29k per sbarazzartene;)
@Rev1.0 Potrei farlo se non richiedesse anche di pensare troppo a inventare un problema / domanda degno di esso e forse non mancasse anche di rimuovere il problema che sto segnalando ma invece di trasmetterlo semplicemente aqualcun altro (che non risponde alle mie preoccupazioni). Buona dimostrazione creativa, però.;)
@jonk: Hehe, diventiamo matti allora;) 1. Crea il secondo account 2. Scrivi una domanda fantastica + taglia con il primo account 3. Rispondi alla domanda pubblicando una risposta fantastica usando il secondo account 4. Elimina il secondo account -> Risultato: hai scritto una buona domanda,una buona risposta e hai persino perso la reputazione mentre lo facevi ... tutto ciò che hai sempre voluto;)
@Rev1.0 (1) Ho la sensazione che ciò violerebbe alcune interpretazioni della politica e mi farebbe bannare.(2) Vorrei ancora che la gente sapesse chi sono e cambiare account praticamente complica o sconfigge questo obiettivo.(3) Qualcuno (anche se sono io) finisce ancora con quei punti rep.(4) Amo il pensiero creativo!Grazie.
Sette risposte:
filo
2018-09-06 16:30:30 UTC
view on stackexchange narkive permalink

Sì.Praticamente tutto in un MCU può essere interrotto da una richiesta di interruzione.Quando il gestore degli interrupt completa, il codice precedente continuerà semplicemente, quindi di solito non è un problema.

In un caso speciale, i gestori di interrupt possono essere interrotti da soli interrupt di priorità più alta (interrupt annidati).

Se una serie di istruzioni non deve essere interrotta, è necessario implementare una sezione critica (fondamentalmente disabilitare globalmente gli interrupt, fare il lavoro, abilitare di nuovo).

Ricorda che, a seconda dell'architettura della CPU di destinazione, una singola riga di C può essere compilata per molte istruzioni di assemblaggio.Un semplice i ++ su un AVR viene compilato in più istruzioni se i è ad esempio uint32_t .

Per quanto riguarda il tuo ultimo paragrafo, presumo che sia vero solo su sistemi a 16/8 bit, giusto?So che stai dicendo AVR .. solo assicurandomi.
memcpy di una struttura (come nella domanda) è più istruzioni anche su ARM a 32 bit.Anche l'incremento di uint64_t su ARM a 32 bit non è atomico.Le operazioni bit per bit sono anche di lettura-modifica-scrittura (a meno che non venga utilizzato il bit-banding).
@HarrySvensson no - su qualsiasi architettura RMW e la maggior parte degli UC sono di lettura - modifica - scrittura (la maggior parte dei processori RISC sono RMW).Quindi i ++ genererà in molti casi (tranne se il valore è semplicemente tenuto nel registro, cosa che non è qui) tre istruzioni anche sui moderni UC ARM a 32/64 bit.
Ah, qui c'è stato un leggero malinteso.Stavo pensando di prendermi cura del riporto durante l'esecuzione di incrementi (overflow), ed entrambi state parlando di recuperare dalla memoria e riscrivere.- Oh bene.
In generale: tutte le operazioni su tipi più larghi della larghezza del bus dati sono "funky".
Sam
2018-09-06 20:25:26 UTC
view on stackexchange narkive permalink

Qualsiasi operazione che non sia atomica può essere disturbata da un interrupt.Questo tipo di programmazione è spesso molto diverso dalla maggior parte degli altri programmi e può creare confusione per le persone che non hanno studiato la progettazione del processore o l'architettura del computer.

Potresti pensare a te stesso "Questo non accadrà mai, quanto tempo ci vuole per copiare questo codice e quanto è probabile che si verifichi un'interruzione?"Ma con la maggior parte delle applicazioni incorporate di produzione accadrà perché il prodotto è attivo per anni senza aggiornamenti.

L'altro problema con le copie di struct come questa è che quando si verificano sono straordinariamente difficili da eseguire il debug perché si verificano solo quando l'interrupt si verifica al momento giusto (che può durare anche un solo ciclo).

Echelon
2018-09-06 18:39:19 UTC
view on stackexchange narkive permalink

Il punto centrale delle interruzioni è che possono (e accadono) tutto il tempo e sono progettate per avere un impatto zero su qualsiasi codice che sia in esecuzione quando si verificano. Tutti i registri vengono salvati e, a seconda dell'architettura della CPU, può essere scambiato un set di registri completamente diverso, l'interrupt fa la sua cosa, quindi i registri originali vengono ripristinati e il codice continua a funzionare normalmente.

Possono verificarsi problemi quando la stessa routine del servizio di interruzione tenta di accedere alla memoria a cui accede il codice interrotto in esecuzione. Errori ancora più sottili possono verificarsi quando un processo di I / O critico in termini di tempo viene interrotto. Questi problemi sono comuni con architetture più vecchie, più semplici e meno sicure in cui può esserci poca separazione tra il codice in modalità "utente" e "supervisore / kernel".

Questo tipo di problema può essere difficile da identificare e spesso difficile da riprodurre, ma una volta identificato è spesso abbastanza banale da risolvere utilizzando la programmazione difensiva, mutex / semafori o semplicemente disabilitando gli interrupt nelle sezioni critiche del codice.

La classe generale di problemi è stata ampiamente studiata e le moderne CPU multi-core e persino i sistemi operativi multi-tasking non sarebbero possibili se non fossero già state provate e testate più soluzioni.

Joshua
2018-09-07 04:32:01 UTC
view on stackexchange narkive permalink

Vado avanti e presumo che tu l'abbia chiesto per un'ottima ragione.

  * Data_external = Data_internal;
 

Può essere diviso (salvo alcuni casi limite che è improbabile che siano in gioco qui).

Non conosco la tua CPU ma non ho ancora visto una CPU che non possa fare l'equivalente morale di:

  cli ();/ * maschera tutti gli interrupt * /
* Data_external = Data_internal;
sti ();/ * ripristina la maschera di interruzione * /
 

Ora non può essere diviso su nessuna CPU single core perché nulla può interrompere mentre gli interrupt sono disattivati.Che questa sia o meno una buona idea dipende da molte cose che semplicemente non sono qualificato per valutare.

Se sei multi-core (e finalmente mi sono ricordato che sul mercato esiste una CPU embedded multi-core) non farlo.Non ha valore.Avresti bisogno di sviluppare un lock appropriato.

Cosa sono cli e sti?da google sembrano essere istruzioni x86?
@Sam: Ebbene sì, quelli sono i nomi delle istruzioni in x86.Penso che abbiano gli stessi nomi nel PDP-11 perché un codice che ha avuto origine lì aveva gli stessi nomi di funzione per un equivalente logico in modalità utente (maschere segnali inter-processo).Ecco le istruzioni per Arduino: https://www.tldp.org/LDP/tlk/dd/interrupts.html
Normalmente disabiliteresti gli interrupt, ma li riabiliteresti solo se fossero effettivamente abilitati.Altrimenti il tuo codice ha l'effetto collaterale di abilitare sempre gli interrupt, anche se erano disabilitati prima che il codice fosse chiamato.
Dmitry Grigoryev
2018-09-07 18:08:31 UTC
view on stackexchange narkive permalink

Il codice così come lo hai presentato può essere effettivamente interrotto.Tuttavia, prima di iniziare a creare sezioni critiche ovunque, dovresti controllare alcune cose:

  • Dici che questa funzione è "all'interno di un driver".Gli interrupt sono già disabilitati quando viene chiamata questa funzione?O è chiamato all'interno di un gestore di interrupt che impedisce l'attivazione di altri interrupt?In caso affermativo, l'operazione non può infatti essere interrotta.

  • È mai stato effettuato l'accesso a Data_internal all'interno di un gestore di interrupt?In caso contrario, non ci sono danni anche se l'operazione può essere interrotta.

studog
2018-09-07 23:49:40 UTC
view on stackexchange narkive permalink

[Rappresentante insufficiente per commentare]

Un altro trucco con quel tipo di copia della struttura è che è una copia superficiale.Potrebbe essere necessaria una copia completa.

Una copia superficiale potrebbe forse, ma non probabilmente, essere atomica, a seconda dell'architettura della macchina.Una copia profonda quasi certamente non è atomica su nessuna architettura.

Un punto giusto;ma è più probabile che una copia profonda sia atomica perché è quasi sempre messa a punto da uno scambio di puntatori.Eppure in questo caso, se avesse dovuto essere una copia profonda, sicuramente non sarebbe atomica.
supercat
2018-09-07 23:51:55 UTC
view on stackexchange narkive permalink

Un'implementazione di qualità adatta all'uso in sistemi embedded documenterà come le letture o le scritture volatili qualificate di vario tipo verranno eseguite in modo sufficientemente dettagliato per indicare se e come possono essere "divise" da interruzioni e anche se le letture e le scritture volatili sono sequenziate rispetto a letture e scritture non qualificate. Sebbene alcune implementazioni possano comportarsi come se tutte le letture e le scritture fossero volatili qualificate, ci si aspetta generalmente che le implementazioni siano libere di elaborare sequenze di letture e scritture non qualificate in qualunque modo sarebbe più efficiente quando ci sono nessun accesso volatile intermedio.

Su un tipico microcontrollore a 32 bit, legge e scrive di tipi interi qualificati volatile di 32 bit e inferiori; un compito consisterà in una lettura atomica seguita da una scrittura atomica. Se vuoi assicurarti che una struttura a 32 bit venga copiata atomicamente, inseriscila in un'unione con un uint32_t e leggi o scrivi quel membro per leggere o scrivere la struttura nel suo insieme. Le implementazioni di qualità che sono configurate per essere adatte all'uso di sistemi embedded consentiranno ai sindacati di essere impiegati in tale modo senza considerare se lo Standard richiederebbe implementazioni che non sono destinate a tale uso per fare altrettanto. Nota che gcc e clang non si comporteranno in modo affidabile come implementazioni di qualità adatte all'uso da parte di sistemi embedded a meno che non siano disabilitate varie ottimizzazioni.



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...