Forum: Mikrocontroller und Digitale Elektronik Cortex Faults: Was macht man im Handler?


von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo Forum,

ich sitze hier gerade an einem Cortex-M4, aber die Frage ist mehr oder 
weniger für alle Cortex-Ms gültig.

Ich habe die Usage-, Bus- und MMU-Faults aktiviert (sonst würde der 
Prozessor bei einem solchen Fault im Hardfaulthandler landen), aber ich 
frage mich jz was man in den entsprechenden Handlern sinnvolles tun 
kann.

Beim Hardfault ist es ja mehr oder weniger klar: ein schwerwiegender 
Fehler ist aufgetreten: eigentlich kann man nur while(1) {} machen und 
dann mit dem Debugger analysieren. Wenn man dann einfach mit dem 
Programm weitermachen würde, dann würde sonst was passieren.

Bei der MMU-Exception ist es aber schon interessanter: was macht man da 
sinnvollerweise? Nur irgenwie mitloggen? (Wobei dieser Fall bei mir 
bisher noch keine Rolle spielt, weil ich die MMU noch nicht nutze)

Ich habe auch die div0-Exception aktiviert, und die landet dann, neben 
Unaligned Access und falschem Coprocessor Access, im UsageFault-Handler.
Was sollte man dort jetzt machen?
- das Div0 würde ich einfach loggen und dann versuchen mit dem Programm 
weitermachen
- Unalinged Access: eigentlich kann man doch fast nur seinen Compiler 
bemängeln oder schauen, was man für Gemeinheiten im Code macht
- nicht vorhandenen Coprozessor benutzt: ?

BusFault: ?

-------

Unterm Strich sehen alle meine Exceptionhandler relativ gleich aus: 
nämlich nur eine Endlosschleife.

Daher meine Frage:
Was sollte man wann sinnvolles tun?
Und nach welcher Exception kann man noch mit einem funktionierenden 
Programm rechnen?

Mit freundlichen Grüßen,
N.G.

PS: zur Verfügung stehen unter anderem:
- Logfile auf SD-Karte
- UART
- LEDs

von W.S. (Gast)


Lesenswert?

N. G. schrieb:
> Daher meine Frage:
> Was sollte man wann sinnvolles tun?

Du hast in deinen Betrachtungen zu allererst nur an den Debugger 
gedacht. Aber das ist nicht die Einsatz-Umgebung deines Controllers. Im 
realen Controller-Leben steht der arme Kerl nämlich allein und einsam 
auf weiter Flur da und bei irgend einer Störung, die da eventuell mal 
hereinrauscht und ihn aus der Bahn wirft, einfach nur per "B ." in sich 
zu gehen und reinweg garnichts mehr zu tun, alte ich für die dümmste 
aller Varianten.

Ich halte viel mehr davon, in solchen Fällen einfach einen gezielten 
Restart zu veranlassen.

Nee, nicht mit dem Holzhammer a la Watchdog, sondern mit einem 
Fehlercode durch den Kaltstart hindurch, so daß die eigentliche Firmware 
eine Chance hat, anhand dieses Fehlercodes den Grund ihres erneuten 
Aufstartens zu berücksichtigen (falls das aus Sicherheitsgründen nötig 
ist).

W.S.

von Dr. Sommer (Gast)


Lesenswert?

N. G. schrieb:
> (Wobei dieser Fall bei mir
> bisher noch keine Rolle spielt, weil ich die MMU noch nicht nutze)

Welcher Cortex-M4 hat denn eine MMU o.O

Die Fault-Handler deuten ja eigentlich immer auf fehlerhaften Code hin. 
Den kann dein Programm ja schlecht beheben. Das gilt auch für Division 
durch Null - einfach mit "irgendeinem" Ergebnis weiterrechnen kann ja 
eigentlich auch nur in einer Katastrophe enden. Einzig sinnvoll wäre es 
den Controller zu resetten oder anzuhalten, und ggf. den Fehler zu 
loggen oder in Endlosschleife per UART o.ä. rauszuschicken.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo,

W.S. schrieb:
> N. G. schrieb:
>> Daher meine Frage:
>> Was sollte man wann sinnvolles tun?
>
> Du hast in deinen Betrachtungen zu allererst nur an den Debugger
> gedacht.
Da hast du durchaus recht.

> Aber das ist nicht die Einsatz-Umgebung deines Controllers. Im
> realen Controller-Leben steht der arme Kerl nämlich allein und einsam
> auf weiter Flur da und bei irgend einer Störung, die da eventuell mal
> hereinrauscht und ihn aus der Bahn wirft, einfach nur per "B ." in sich
> zu gehen und reinweg garnichts mehr zu tun, alte ich für die dümmste
> aller Varianten.
Naja, vor dem while(1) gibts natürlich noch eine Error-Ausgabe mittels 
LED o.Ä.

> Ich halte viel mehr davon, in solchen Fällen einfach einen gezielten
> Restart zu veranlassen.
dann läuft die Firmware ja irgendwann wieder in den Fault. Und am 
schlimmsten ist: ich bekomme es als Programmierer wenns ganz schlecht 
läuft nicht einmal mit!

> Nee, nicht mit dem Holzhammer a la Watchdog, sondern mit einem
> Fehlercode durch den Kaltstart hindurch, so daß die eigentliche Firmware
> eine Chance hat, anhand dieses Fehlercodes den Grund ihres erneuten
> Aufstartens zu berücksichtigen (falls das aus Sicherheitsgründen nötig
> ist).
Das ist mehr oder weniger Geschmackssache.


Hallo,
Dr. Sommer schrieb:
> N. G. schrieb:
>> (Wobei dieser Fall bei mir
>> bisher noch keine Rolle spielt, weil ich die MMU noch nicht nutze)
>
> Welcher Cortex-M4 hat denn eine MMU o.O
Uuuups, MPU war gemeint... Asche auf mein Haupt.

> Die Fault-Handler deuten ja eigentlich immer auf fehlerhaften Code hin.
> Den kann dein Programm ja schlecht beheben.
Genau. Aber irgendwas muss man ja machen, damit der fehlerhafte Code 
behoben werden kann.

> Das gilt auch für Division
> durch Null - einfach mit "irgendeinem" Ergebnis weiterrechnen kann ja
> eigentlich auch nur in einer Katastrophe enden.
Naja, wenn man die Exception nicht aktiverit, rechnet der Core sowieso 
mit 0 als Quotient weiter. Wobei z.B. Unendlich mehr Sinn machen würde.
Das wäre evtl. auch mein Vorgehen.

> Einzig sinnvoll wäre es
> den Controller zu resetten oder anzuhalten, und ggf. den Fehler zu
> loggen oder in Endlosschleife per UART o.ä. rauszuschicken.
Okay, so hab ich mir das fast gedacht.

Dazu aber noch eine Frage: Kann man bei jeder Exception gefahrlos C-Code 
schreiben? Ich würde aus dem Bauch raus behaupten: Nein.


Danke aber schonmal an euch

von Dr. Sommer (Gast)


Lesenswert?

N. G. schrieb:
> Dazu aber noch eine Frage: Kann man bei jeder Exception gefahrlos C-Code
> schreiben? Ich würde aus dem Bauch raus behaupten: Nein.

Naja, du solltest dich natürlich nicht auf den Zustand des Programms 
verlassen, also a priori annehmen dass in allen Variablen Unfug steht 
(deswegen wird auch das Loggen auf die SD-Karte schwierig - deren 
Ansteuerung inkl. Dateisystem ist ja sehr komplex, es ist nicht gerade 
wahrscheinlich dass genau das noch perfekt funktioniert). Das 
Hauptproblem ist dass der Stack übergelaufen/voll sein könnte, und daher 
lokale Variablen nicht funktionieren könnten. Daher wäre es vermutlich 
sinnvoll, den Stack bei Betreten des Handlers zu resetten. Danach 
solltest du aber normalen C-Code schreiben können, verlass dich aber 
besser nicht auf den Status des Programms. Am besten initialisierst du 
auch den UART neu, bevor du über den was rausschickst o.ä.

N. G. schrieb:
> Naja, wenn man die Exception nicht aktiverit, rechnet der Core sowieso
> mit 0 als Quotient weiter
Und das ist garantiert sowieso völlig falsch ;-)

N. G. schrieb:
> Wobei z.B. Unendlich mehr Sinn machen würde.
> Das wäre evtl. auch mein Vorgehen.
Geht ja auch nur bei float, und auch dann wird die unendlich vermutlich 
zu verkehrten/komischen Ergebnissen am Ende führen (NaN oder inf). Daher 
halte ich auch das für wenig sinnvoll und würde bei Division durch Null 
immer anhalten.
Andersherum gefragt: Welcher Algorithmus funktioniert noch richtig, der 
eine Division durch Null durchführt und Unendlich als Ergebnis erhält? 
Ist ein Algorithmus, der durch Null teilt, nicht grundsätzlich 
fehlerhaft und in dem Fall nicht zu gebrauchen? Onehin sollte man 
(gerade auf schwer debuggbaren Embedded Systemen) bei Divisionen 
vorher immer auf 0 prüfen, genauso wie man bei Addition/Subtraktion 
vorher auf Überlauf prüfen sollte. Dann kann man direkt gescheit 
reagieren, anstelle im Error Handler ein Ergebnis zu "raten" und zu 
hoffen, dass alle betroffenen Algorithmen damit klar kommen.

von W.S. (Gast)


Lesenswert?

N. G. schrieb:
> dann läuft die Firmware ja irgendwann wieder in den Fault. Und am
> schlimmsten ist: ich bekomme es als Programmierer wenns ganz schlecht
> läuft nicht einmal mit!

Nö. In den allermeisten Fällen passieren solche Abstürze nicht durch 
falsche Programmierung, sondern durch äußere Einflüsse - und sowas ist 
entweder nicht zyklisch oder es ist ohnehin nichts mehr zu machen. Im 
ersteren Fall rappelt sich der µC eben wieder hoch und tut seinen Dienst 
wieder.

Im zweiten Fall geht ohnehin nichts mehr, z.B. ständiger Brownout oder 
so, dann ist an ein Weiterarbeiten ohnehin nicht mehr zudenken.

Aber die ersteren Fälle sind damit erledigt, das System ist robuster als 
mit bloßem Stehenbleiben.

Und als Programmierer kriegst du sowas allemal mit, wenn du das willst.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> Nö. In den allermeisten Fällen passieren solche Abstürze nicht durch
> falsche Programmierung, sondern durch äußere Einflüsse
Woher nimmst du denn diese Statistik? Ich benutze z.B. STM32 in einem 
doch sehr störverseuchten Umfeld (ja, eigentlich nicht die optimale 
Wahl), und bisher war jeder Absturz ein Programmierfehler.  Unter 
anderem verursacht durch Kollegen, die fröhlich durch eine Zahl teilen, 
die per Bus reinkam, ohne zu prüfen ob sie 0 sein könnte...
Externe Einflüsse wirken sich doch wesentlich subtiler aus (leicht 
abweichende Zahlen usw.) als direkt freundlicherweise einen sauberen 
Absturz auszulösen.

von W.S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Andersherum gefragt: Welcher Algorithmus funktioniert noch richtig, der
> eine Division durch Null durchführt und Unendlich als Ergebnis erhält?
> Ist ein Algorithmus, der durch Null teilt, nicht grundsätzlich
> fehlerhaft und in dem Fall nicht zu gebrauchen?

Nein. In den allermeisten Fällen kommen Divisionen durch 0 oder extrem 
kleine Werte aufgrund äußerer Umstände vor, als da wären menschliche 
Fehler bei Kalibrierungen, Überläufe oder Fehler bei Datenübertragungen, 
Störungen bei Sensoren usw.

Natürlich kann man sowas alles abfangen (if(fabs(x)<1E-15)...), aber 
sowas ist ne Unannehmlichkeit, weswegen ich es durchaus vorziehen würde, 
wenn auch bei float die Rechenlogik sättigend funktionieren würde. Bei 
Filteranwendungen z.B. kann man sich nämlich aus Zeitgründen keine 
ausufernden Bereichsprüfungen von Argumenten erlauben.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> Natürlich kann man sowas alles abfangen (if(fabs(x)<1E-15)...), aber
> sowas ist ne Unannehmlichkeit, weswegen ich es durchaus vorziehen würde,
> wenn auch bei float die Rechenlogik sättigend funktionieren würde.
Du willst also Rechenergebnisse, die aus falschen Eingaben aufgrund von 
Bus-/Mess-/Kalibrier-Fehlern entstanden sind, trotzdem behalten? Na 
hoffentlich steuerst du keine gefährlichen Maschinen mit solchen 
falschen Daten!

W.S. schrieb:
> Bei
> Filteranwendungen z.B. kann man sich nämlich aus Zeitgründen keine
> ausufernden Bereichsprüfungen von Argumenten erlauben.
Wenn du einen Filter hast, der durch eine Eingabe teilt, und bei dem 
du keinen einzelnen Takt für so etwas opfern kannst, und der völlig 
isoliert auf dem Controller läuft (damit die Exception nicht andere 
Algorithmen beeinflusst), und der bei falscher Eingabe plötzlich sehr 
viel Rechenzeit übrig hat (Exception-Entry & Exit ist nicht gerade 
gratis), dann kannst du das so machen, aber im Allgemeinen würde ich das 
doch mindestens als sehr unsauber oder geradezu gefährlich (s.o.) 
betrachten.

von Nop (Gast)


Lesenswert?

Man kann mit ein wenig Assembler den Exception-Stack untersuchen und da 
die Programmadresse rauspfriemeln, an der die Exception ausgelöst wurde. 
SP+24 ist das. Die Routine muß dazu natürlich in Assembler sein und kann 
auch gleich noch alle Interrupts abschalten.

Sobald man Absturzadresse ermittelt hat, wirft man diese Daten in R0 und 
brancht dann zur C-Routine für die weitere Verarbeitung. Diese bekommt 
einen uint32_t als Parameter und sollte als "used" markiert werden, weil 
der Compiler deren Aufruf aus dem Inline-Assembler nicht unbedingt 
"sieht". Das Auslesen des fault registers kann diese Routine dann auch 
in C erledigen. Dann weiß man, warum die Software wo abgestürzt ist.

Das Gemeine an der Stelle ist: man kann nur entweder auf stack overflow 
reagieren oder für die anderen exceptions die Adresse rauskriegen. 
Beides geht nicht.

Denn wenn man wegen stack overflow im hard fault landen kann, muß man 
die Routine als naked definieren, weil das Pushen des exception stacks 
direkt WIEDER einen stack overflow auslösen würde.

Aber stack overflow ist per Analyse ausschließbar. Hierzu muß man sich 
den call tree des Programmes analysieren. Die Daten kriegt man bei GCC 
mit der Compiler-Option -fstack-usage in .su-Files als text ausgegeben. 
Irgendwo habe ich dazu auch mal Auswertescripte gesehen. Keil wirft 
einem diese Daten gleich sinnvoll aufbereitet raus.

Also worst case für den call tree der Applikation annehmen (bzw. aller 
Tasks zugleich) und dann davon ausgehen, daß sämtliche Interrupts genau 
in dem Moment AUCH noch auflaufen. Das ist dann der Stackbedarf, den man 
dimensionieren muß. Vielleicht noch ein kB draufschlagen, nur zur 
Sicherheit. Das sollte man sowieso machen, weil es leichter ist, Fehler 
auszuschließen, als sie zu debuggen.

Bei allen anderen Exceptions weiß man dann, daß zumindest der Stack noch 
geht. Systemtimer geht nicht mehr, andere Interrupts auch nicht mehr. 
Aber Delay-Schleifen via DWT gehen noch, ebenso wie IO im Polling-Modus. 
Das reicht, um z.B. Sachen auf einem Display oder UART im Polling-Modus 
auszugeben.

Was außerdem noch geht, ist der Zugriff aufs Backup-RAM und die 
RTC-Backup-Register. Hier kann man Systemzeit, Systemfehler (Inhalt des 
fault registers) und die ermittelte Absturzadresse speichern. Wenn man 
richtig gründlich ist, bildet man irgendeine Art von Checksumme über 
diese Fehlerdaten und speichert die auch noch mit ab. Das schließt aus, 
daß man beim Hochfahren Datenmüll irrtümlich als Fehler einliest. Dann 
Reset via Watchdog.

Beim Hochfahren guckt man an genau diese Stellen im Backup-RAM bzw. den 
Backup-Registern, ob da was steht. Wenn ja, gibt man das aus, loggt es, 
was weiß ich. Das System funktioniert ja dank Reboot erstmal wieder, 
auch Dateisysteme sind damit nutzbar. Dann setzt man diese 
Speicherstellen wieder zurück.

von S. R. (svenska)


Lesenswert?

N. G. schrieb:
> Beim Hardfault ist es ja mehr oder weniger klar: ein schwerwiegender
> Fehler ist aufgetreten: eigentlich kann man nur while(1) {} machen und
> dann mit dem Debugger analysieren. Wenn man dann einfach mit dem
> Programm weitermachen würde, dann würde sonst was passieren.

Der Motor dreht gerade schnell, dann kommt ein kosmischer Strahl 
(ungültige Eingabe, Programmfehler) und haut ihm ein Bit weg, der 
Controller geht in eine Endlosschleife und blinkt eine LED. Bremspedal, 
Aufprallsensoren, Airbags, alles egal, ich sage ja, dass ich gerade 
kaputt bin.

Wenn es so sehr knallt, dass du dein Programm nicht mehr sinnvoll 
fortsetzen kannst, dann musst du möglichst schnell einen sicheren 
Zustand herstellen. Wie der aussieht und wie schnell er da sein muss, 
hängt vom Anwendungsfall ab.

von Nop (Gast)


Lesenswert?

W.S. schrieb:

> Nein. In den allermeisten Fällen kommen Divisionen durch 0 oder extrem
> kleine Werte aufgrund äußerer Umstände vor

Falsch. Das sind schlichtweg Softwarefehler.

> als da wären menschliche Fehler bei Kalibrierungen

Kalibrierdaten validiert man beim Hochfahren. Was passiert, wenn man das 
nicht tut, konnte man letztes Jahr in Spanien beobachten, als ein A400M 
abgestürzt ist, mit etlichen Toten.

> Überläufe oder Fehler bei Datenübertragungen,

Einkommende Daten validiert man ebenfalls. Datenübertragungen sichert 
man.

> Störungen bei Sensoren usw.

Auch diese muß man auf gültige Wertebereiche prüfen. Allein schon, weil 
Kabelbruch den Sensor out of range werfen kann.

> Natürlich kann man sowas alles abfangen

Das sollte man auch.

> Bei
> Filteranwendungen z.B. kann man sich nämlich aus Zeitgründen keine
> ausufernden Bereichsprüfungen von Argumenten erlauben.

Die prüft man vorher. Ggf. kann man seine Filter auch auf dem PC 
simulieren, um deren Stabilität sicherzustellen. Ganz besonders, wenn 
man Filter verwendet, die Divisionen vorsehen, typischerweise 
IIR-Filter. Die haben IMMER das Problem, daß sie instabil werden 
könnten, und da hat man zu prüfen, ob die Polstellen wirklich allesamt 
in der linken Hälfte der Z-Ebene liegen.

Aber einfach nur nichts abprüfen und ggf. einen Absturz zu riskieren, 
ist einfach grober Pfusch in der Software. Der einzige "äußere Umstand", 
der dafür verantwortlich ist, ist der Programmierer.

von Nop (Gast)


Lesenswert?

S. R. schrieb:

> Der Motor dreht gerade schnell, dann kommt ein kosmischer Strahl
> (ungültige Eingabe, Programmfehler) und haut ihm ein Bit weg

Bei wirklich kritischen Maschinen ist es an sich schon ein Designfehler 
im System, wenn nur ein Controller die Sache regelt.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo Nop,
vielen Dank für deine kompetente Erklärung, ich werde das so ähnlich 
umsetzen. Leider hat mein µC kein Backup-RAM o.Ä., aber es findet sich 
ja immer ein Weg ;)

Hallo,
S. R. schrieb:
> N. G. schrieb:
>> Beim Hardfault ist es ja mehr oder weniger klar: ein schwerwiegender
>> Fehler ist aufgetreten: eigentlich kann man nur while(1) {} machen und
>> dann mit dem Debugger analysieren. Wenn man dann einfach mit dem
>> Programm weitermachen würde, dann würde sonst was passieren.
>
> Der Motor dreht gerade schnell, dann kommt ein kosmischer Strahl
> (ungültige Eingabe, Programmfehler) und haut ihm ein Bit weg, der
> Controller geht in eine Endlosschleife und blinkt eine LED. Bremspedal,
> Aufprallsensoren, Airbags, alles egal, ich sage ja, dass ich gerade
> kaputt bin.
>
> Wenn es so sehr knallt, dass du dein Programm nicht mehr sinnvoll
> fortsetzen kannst, dann musst du möglichst schnell einen sicheren
> Zustand herstellen. Wie der aussieht und wie schnell er da sein muss,
> hängt vom Anwendungsfall ab.
Du hast natürlich recht, allerdings spielt das in meiner Anwendung keine 
Rolle, da sie nichts Sicherheitskritisches enthält. Ganz nebenbei ist 
immer ein Mensch dabei, der im Fehlerfall reagieren kann.

Alles in allem kann man wohl mal wieder sagen: "Es kommt darauf an".
Je nach Anwendung muss man im Fehlerfall anders reagieren.

Danke an alle.
N.G.

von Nop (Gast)


Lesenswert?

N. G. schrieb:
> vielen Dank für deine kompetente Erklärung, ich werde das so ähnlich
> umsetzen. Leider hat mein µC kein Backup-RAM o.Ä., aber es findet sich
> ja immer ein Weg ;)

Klar :-)

Du kannst auch einen Teil des RAM als Fehlerspeicher reservieren, 
einfach mit einem kleinen struct im BSS-Segment, also als globale 
Variable (mit volatile!). Dann aber wirklich mit Checksumme. Wenn Du 
jetzt beim Hochfahren den Assembler-Startup-Code etwas modifizierst 
(also wo das RAM genullt wird), kannste den Inhalt des structs in drei 
Register laden (Adresse, Fault, Checksumme), dann das RAM initialisieren 
und dann wieder ins struct zurückladen. Das struct kannste dann im 
C-Code auswerten. So geht der beschriebene Mechanismus auch ohne 
Backup-RAM.

Übrigens, die Programmadresse kann man leicht mit dem Mapfile abgleichen 
und weiß, in welcher Funktion das passiert sein muß. Kann fies werden, 
wenn man dem Compiler das Inlinen von Funktionen erlaubt, weil man dann 
nicht mehr so einfach nachvollziehen kann, zu welcher Funktion die 
Adresse gerade gehört. Für Debugzwecke daher lieber mit -fno-inline 
arbeiten.

Die "bequeme" Lösung ist natürlich, das Programm mit dem Debugger 
reinzuladen und vor dem Loslaufen an die Programmadresse zu scrollen, an 
der der Absturz war. Dann sieht man (sofern kein Inlining) sehr direkt, 
wo das im Quelltext war.

von S. R. (svenska)


Lesenswert?

Nop schrieb:
>> Der Motor dreht gerade schnell, dann kommt ein kosmischer Strahl
>> (ungültige Eingabe, Programmfehler) und haut ihm ein Bit weg
>
> Bei wirklich kritischen Maschinen ist es an sich schon ein Designfehler
> im System, wenn nur ein Controller die Sache regelt.

Und kein wahrer Schotte würde das je so entwerfen, ne? :-)
(Kontext: https://de.wikipedia.org/wiki/Kein_wahrer_Schotte)

Nimm den gewöhnlichen billigchinesischen Solarcontroller: 
Leistungstransistor stirbt mit Kurzschluss, Controller bekommt 
unplausible Werte, wirft Exception und zeigt statt "Not-Aus" nur eine 
Fehler-LED. Nach ein paar Minuten brennt die Bude. Auch doof.

von Nop (Gast)


Lesenswert?

S. R. schrieb:

> Und kein wahrer Schotte würde das je so entwerfen, ne? :-)

Moment, daß es ein Designfehler ist, heißt ja nicht, daß er nicht 
begangen würde - sogar da, wo es dann Ärger gibt. Siehe den Skandal um 
den Toyota Camry, dessen Software ein einziger Haufen Dreck war, und wo 
deswegen auch Leute gestorben sind. Da das allerdings in den USA war und 
nicht in Europa, wurde das dementsprechend teuer für Toyota.

von S. R. (svenska)


Lesenswert?

Du hast zwischen "kritischen Maschinen" und "wirklich kritischen 
Maschinen" gerade nach diesem Designkriterium unterschieden. Diese 
Unterscheidung ist Unsinn, wie du ja gerade selbst geschrieben hast. Nur 
darauf wollte ich dich hinweisen.

Wir sind uns einig, dass die beste (sinnvollste) Lösung vom konkreten 
Anwendungsfall abhängt.

von Nop (Gast)


Lesenswert?

S. R. schrieb:
> Du hast zwischen "kritischen Maschinen" und "wirklich kritischen
> Maschinen" gerade nach diesem Designkriterium unterschieden.

Ah jetzt ja, das war natürlich redundant, stimmt. :-)

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Also nochmal ein großes Danke an alle, die sich an der Diskussion 
beteiligt haben!

Ich weiß, dass diese Frage sehr allgemein Formuliert war, und es 
deswegen leicht sehr gegensätzliche Meinungen geben kann.

Bei einem konkreten Problem melde ich mich wieder (oder der schönere 
Fall: ich melde mich nicht wieder, es gibt schließlich keine Probleme 
;-) )

Mit freundlichen Grüßen,
N.G.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.