Funktion aufgerufen in ISR und Overlay Direktive -Keil/8051 core

Mein C-Code hat eine ISR, wo eine Entscheidung getroffen werden muss, um eine bestimmte Funktion "A" auszuführen. Jetzt weiß ich, dass es nicht gut ist, eine Funktion in einem ISR auszuführen. Aber in diesem Fall meiner Bewerbung sehe ich keinen anderen Ausweg. Nach dem Aufruf der Funktion "A" bemerkte ich einen plötzlichen Sprung in der Größe der verbrauchten Daten und die plötzliche WARNUNG L15, die in KEIL ERLÄUTERUNG DER WARNUNG erklärt wird .

Ich bin mir sicher, dass die Funktion "A" nicht wiedereintrittsfähig ausgeführt wird, aber sie verbraucht mit Sicherheit physischen Speicher. sowohl Funktion "A" als auch Funktionen, die sie aufruft. (Dies bezieht sich meiner Meinung nach auf die in den Funktionen deklarierten Variablen).

Erstens, gibt es eine Möglichkeit, diesen Schuss im Datenspeicherplatz zu vermeiden?

Zweitens möchte ich die Methode 2 anwenden, wie in der Keil-Erklärung gezeigt. Aber ich weiß nicht, wie und wo genau ich die OVERLAY-Direktive in meinen Code einfügen soll. Bei der Initialisierung? Bei Funktion Deklaration? Vor Funktionsdefinition? Wo genau?

WARNENDES BEISPIEL in meinem Code

*** WARNING L15: MULTIPLE CALL TO FUNCTION
NAME:    _IECLOC_FUN/DATA_ACCESS
CALLER1: ?C_C51STARTUP
CALLER2: TIMER_ISR/TIMER

WARNUNG BEDEUTUNG

Korrekturen, Vorschläge, Codebeispiele und Links sind willkommen. Ich hoffe, diese Frage ist klar.

Danke an alle.

Antworten (2)

Bitte haben Sie Verständnis dafür, dass bei Keil auf 8051-Kernen die lokalen Variablen der Subroutine und alle Eintragsargumente, die über das hinausgehen, was in Register passen würde, der Compiler RAM für die Platzierung dieser zuweist. Der Linker hat dann die komplizierte Aufgabe, die vollständige Aufrufbaumstruktur Ihres Programms zu analysieren und den für diese Zwecke zugewiesenen Speicherpool zu optimieren, um die erforderliche RAM-Menge zu minimieren. Diese Minimierung verwendet gegenseitigen Ausschluss zwischen Codeaufrufsequenzen, um zu bestimmen, welche Teile des Speicherpools von Codepfaden gemeinsam genutzt werden können, die sich im Ausführungsfluss nicht überschneiden.

Wenn Sie einen ISR-Aufruf in die Mischung der Code-Aufrufstruktur einfügen, kann der Linker nicht bestimmen, ab welchem ​​Punkt der Interrupt ins Spiel kommen kann. Es könnte jederzeit während eines der gegenseitigen Ausschlusspfade auftreten, die der Linker im normalen Hauptcode gefunden hat. Das bedeutet, dass der Linker die Subroutine aus dem Shared-Usage-Pool ziehen und Datenraum speziell für die lokalen Variablen der Subroutine und vielleicht sogar einige ihrer Eingangsargumente zuweisen muss. Ohne dies würden die gemeinsam genutzten Speicherpools von anderen sich gegenseitig ausschließenden Codeausführungspfaden verschmutzt und das Programm würde in strahlendem Glanz abstürzen.

Die Herausforderung beim Codieren auf einem 8051-Kern besteht darin, von Designs wegzukommen, die viele lokale Variablen verwenden, viele Eingangsargumente haben und Aufrufkontexte haben, die zwischen Hauptcode und Interrupts geteilt werden. Sie müssen wirklich die Freiheiten einschränken, die Sie mit anderen Architekturen erhalten, die einen Stack haben, der für die Übergabe von Subroutinenargumenten und lokalen Variablen verwendet wird. Keil entschied sich dafür, nicht alles auf dem Stack zu implementieren und produzierte daher ein Toolset, das eine Leistung und Optimierung bietet, die in der Branche für die 8051-Architektur erstklassig ist. Aus diesem Grund ist es wichtig, einen Codierungsstil anzupassen, der in das Keil-Schema einfließt.

In Ihrem Fall empfehle ich Ihnen wirklich, Ihre Feststellung zu überdenken, dass diese Subroutine sowohl aus dem Mainline-Kontext als auch aus dem Interrupt-Kontext aufgerufen werden muss. Versuchen Sie, eine Designtechnik zu finden, die dies vermeidet, und Ihr Leben wird viel einfacher.

@Micheal Karas ......... irgendwelche Vorschläge für Designtechniken?
Ich habe sie schon gegeben. Hören Sie auf, Funktionen von Interrupts aufzurufen. Wenn Sie das absolut nicht können, minimieren oder besser eliminieren Sie lokale Variablen in Unterprogrammen, die aus dem Interrupt-Kontext aufgerufen werden. Minimieren oder besser noch beseitigen von Aufrufargumenten in Routinen, die aus dem Interrupt-Kontext aufgerufen werden. Machen Sie die aufgerufene Subroutine flach, indem sie keine anderen Subroutinen oder Bibliotheksfunktionen aufruft.

Die OVERLAYDirektive ist ein Befehl an den Linker und geht überhaupt nicht in Ihren Quellcode. Sie können Anweisungen auf der BL51-Befehlszeile platzieren, aber für alles, was nicht trivial ist, ist es normalerweise besser, sie in eine separate Linker-Befehlsdatei zu schreiben und diese Datei mit der Syntax auf der Befehlszeile an den Linker zu übergeben BL51 @<commandfile>.

Siehe die Befehlszeilenreferenz für BL51 hier .

summen! Das geht tiefer als ich dachte!