Moin,
sorry..... aktuell kommen grad echt ne Menge Fragen auf, die teilweise
nicht eindeutig zu beantworten sind durch Googlen :-)
habe mir bis gestern um 2 Uhr und heute morgen weiter mal meinen kleinen
NMEA Parser geschrieben für den GPS RMC Satz. Mehr brauche ich nicht,
daher auch nix aus dem Netz besorgt. Für die 4 Werte.
Das liegt derzeit alles im ISR Handler, wenn die USART das letzte Byte
erkannt hat und danach 1s Pause ist. Bläht den Code aber mal eben so um
5 kb auf durch die String Funktionen und 1 x float Rechnung.
Der nicht optimierte Code (-O0) braucht nach Messung mit dem DWT Counter
3800 Zyklen für vollen Durchlauf.
Gibt es da eine Schmerzgrenze? Oder sollte man besser ein Flag setzen,
damit das in der arbeitslosen Hauptroutine erledigt wird? Aktuell läuft
alles über INTs, die ganze Datensammelei, das Ein/Aus der Peripherie
usw.
Würde mich mal interessieren, wie die Profis das so machen?
1
/* UART1 Interrupt Service Routine */
2
voidUSART1_IRQHandler(){
3
4
#define MAX_NMEA_FIELDS 16
5
staticchar*nmea_fields[MAX_NMEA_FIELDS];
6
7
/* GPS Empfang abgeschaltet? Dann alles verwerfen */
Christian J. schrieb:> Gibt es da eine Schmerzgrenze?
Das kommt ganz auf deine Anwendung an. Während diese ISR läuft, sind
alle niedriger priorisierten Interrupts gesperrt.
Wenn die ISR zur Verarbeitung der Daten länger braucht, als die nächsten
Daten herein kommen, hast du ganz sicher eine Schmerzgrenze
Überschritten.
Stefan ⛄ F. schrieb:> Das kommt ganz auf deine Anwendung an. Während diese ISR läuft, sind> alle niedriger priorisierten Interrupts gesperrt.
Klar, logisch.... dachte nur es gibt da heilige Grals, die man nicht
verletzten sollte.
Nimmt man zb das Wörtchen static hier weg klappt die Auswertung schon
nicht mehr, da bleiben Felder dann leer. Ohne mir das genau angeschaut
zu haben was da jetzt nicht klappt. Normalerweise deklariere ich alles
als static im Int, damit es im .data (oder .bss?) Bereich liegt damit da
keine "Stack Geschichten" passieren können.
static char* nmea_fields[MAX_NMEA_FIELDS];
Christian J. schrieb:> Nimmt man zb das Wörtchen static hier weg klappt die Auswertung schon> nicht mehr, da bleiben Felder dann leer. Ohne mir das genau angeschaut> zu haben was da jetzt nicht klappt. Normalerweise deklariere ich alles> als static im Int, damit es im .data (oder .bss?) Bereich liegt damit da> keine "Stack Geschichten" passieren können.
Gutgemeinter Rat: Besorg Dir ein C-Buch.
Dein Code macht mir Angst...
Der strncpy macht nicht das, was du dir vorstellst.
Zum anderen: String-Funktionen in Interrupts zu benutzen ist unsauber.
POSIX erlaubt sie z.B. nicht in signal-Handlern. Die, die du benutzt,
sind wahrscheinlich OK aber es gab Zeiten, wo sie z.B. auf x86
sporadisch nicht funktionierten (direction-flag falsch). Komplexere wie
z.B. strtok oder printf sind immer ein no-go.
foobar schrieb:> Der strncpy macht nicht das, was du dir vorstellst.
Und was macht er? Das sah vorher anders aus und wurde nur zusammen
geschrumpft. Der Rückgabewert ist aber ein Zeiger auf das was ich haben
will. Laufen tut es zumindest. Wie geht es besser?
PS: Es fehlt der \0 Terminator, der wird ja nicht kopiert. Das klappt
also nur zufällig.
Declaration
Following is the declaration for strncpy() function.
char *strncpy(char *dest, const char *src, size_t n)
Parameters
dest − This is the pointer to the destination array where the content is
to be copied.
src − This is the string to be copied.
n − The number of characters to be copied from source.
Return Value
This function returns the final copy of the copied string.
Habs schon, danke !!!!
Fehlersicher ist das sowieso nicht, sobald der String nicht so ist wie
erwartet fliegt das alles aus der Kurve :-( Wobei alle static Vars 0
sind beim Start des Systems, allerdings nicht wenn der Speicher sich vom
Stack geklaut wird, dann steht da Müll drin.
Welche Regeln sollte man beachten?
1. ISR wird 'priviligiert' ausgeführt.
2. Eine höhere Priorität unterbricht eine niedrigere.
3. Die ISR sollte enden, bevor sie wieder angesprungen wird (werden
sollte).
Und immer erstmal das IT Flag löschen, wenns gesetzt ist, egal, was
später passiert.
Das ist besonders bei externen (GPIO) Interrupts wichtig.
Beim Initialisieren der IRQ Quelle die Pendings löschen.
Delays, die auf sys_tick basieren, hängen in ISRs, weil sys_tick meist
eine niedrige Priorität hat - ist eigentlich logisch und macht man
sowieso nicht, kann aber im Fehlerfall Kopfzerbrechen bereiten.
Matthias S. schrieb:> Delays, die auf sys_tick basieren, hängen in ISRs, weil sys_tick meist> eine niedrige Priorität hat - ist eigentlich logisch und macht man> sowieso nicht, kann aber im Fehlerfall Kopfzerbrechen bereiten.
Naja, wer einen Delay in einer ISR verwendet gehört eigentlich auch an
den Ei... aufgehängt :-)
Christian J. schrieb:> Naja, wer einen Delay in einer ISR verwendet gehört eigentlich auch an> den Ei... aufgehängt :-)
Es sind Fälle vorstellbar, wo mans trotzdem braucht. Ich hatte z.B. mal
prellende Hallsensoren in einem BLDC, musste aber unbedingt den Sensor
auswerten. Da konnte es schon mal passieren, das man ein paar µs warten
muss.
Aber ich schrieb ja auch:
Matthias S. schrieb:> und macht man> sowieso nicht