Ich verwende den PIC18F13K22 und den C18-Compiler von Microchip in MPLABX. Der PIC setzte sich immer wieder zurück, als er kurz davor war, in die Interrupt-Service-Routine (ISR) zu springen. Ich konnte das Problem auf die Deklaration eines Arrays zurückführen:
UINT16 rom periods[] = {64000,59412,55438,51962, ...} // 1024 Values
Wenn ich die Größe des Arrays auf wenige Elemente verkleinere, läuft der PIC ohne kontinuierliches Zurücksetzen.
Jetzt frage ich mich, warum das große Array einen Reset verursacht. Und noch interessanter für mich: Kann ich irgendwie einen Datensatz deklarieren, der diese 1024 Werte enthält?
Section Type Address Location Size(Bytes)
--------- --------- --------- --------- ---------
_entry_scn code 0x000000 program 0x000006
.cinit romdata 0x000006 program 0x000002
.romdata_Main.o romdata 0x000008 program 0x000800
.code_Main.o code 0x000808 program 0x000124
_cinit_scn code 0x00092c program 0x00009e
.code_Debug.o code 0x0009ca program 0x000080
.code_Signal.o code 0x000a4a program 0x000040
PROG code 0x000a8a program 0x00003c
.code_t0open.o code 0x000ac6 program 0x000038
.code_ADC.o code 0x000afe program 0x000032
.stringtable romdata 0x000b30 program 0x000026
.code code 0x000b56 program 0x000020
_startup_scn code 0x000b76 program 0x00001c
.code___init.o code 0x000b92 program 0x000002
.romdata_t0open.o romdata 0x000b94 program 0x000000
.idata___init.o_i romdata 0x000b94 program 0x000000
.idata_t0open.o_i romdata 0x000b94 program 0x000000
.romdata_Debug.o romdata 0x000b94 program 0x000000
.idata_Debug.o_i romdata 0x000b94 program 0x000000
.romdata___init.o romdata 0x000b94 program 0x000000
.romdata_Signal.o romdata 0x000b94 program 0x000000
.idata_Signal.o_i romdata 0x000b94 program 0x000000
.idata_Main.o_i romdata 0x000b94 program 0x000000
.romdata_ADC.o romdata 0x000b94 program 0x000000
.idata_ADC.o_i romdata 0x000b94 program 0x000000
.code_c018i.o code 0x000b94 program 0x000000
.romdata_c018i.o romdata 0x000b94 program 0x000000
.idata_c018i.o_i romdata 0x000b94 program 0x000000
.config_300001_Main.o romdata 0x300001 program 0x000001
.config_300002_Main.o romdata 0x300002 program 0x000001
.config_300003_Main.o romdata 0x300003 program 0x000001
.config_300005_Main.o romdata 0x300005 program 0x000001
.config_300006_Main.o romdata 0x300006 program 0x000001
MATH_DATA udata 0x000000 data 0x000014
.tmpdata udata 0x000014 data 0x000000
.stack udata 0x000060 data 0x000050
.udata_c018i.o udata 0x0000b0 data 0x00000a
.udata_Signal.o udata 0x0000ba data 0x000002
.idata_c018i.o idata 0x0000bc data 0x000000
.udata_ADC.o udata 0x0000bc data 0x000000
.idata_ADC.o idata 0x0000bc data 0x000000
.udata_Main.o udata 0x0000bc data 0x000000
.idata_Main.o idata 0x0000bc data 0x000000
.idata_Signal.o idata 0x0000bc data 0x000000
.udata_Debug.o udata 0x0000bc data 0x000000
.idata_Debug.o idata 0x0000bc data 0x000000
.udata_t0open.o udata 0x0000bc data 0x000000
.idata_t0open.o idata 0x0000bc data 0x000000
.udata___init.o udata 0x0000bc data 0x000000
.idata___init.o idata 0x0000bc data 0x000000
SFR_UNBANKED0 udata 0x000f68 data 0x000098
Es gibt keinen inhärenten Grund, warum dieses Array einen Reset verursachen sollte. Sie deklarieren anscheinend 2 kByte Konstanten im Programmspeicher. Dieser PIC hat 8 kByte Programmspeicher, das sollte also in Ordnung sein.
Wahrscheinlicher ist, dass es an anderer Stelle einen Fehler gibt. Dieses Array ist wahrscheinlich das Größte, was der Linker platzieren muss, sodass sich der gesamte Code, der sich nicht an bestimmten festen Adressen befindet, wahrscheinlich bewegt, wenn die Arraygröße geändert wird, was dazu führen kann, dass einige Fehler auftreten und verschwinden.
Es könnte nützlich sein, den Teil "Section Info" der Linker-MAP-Datei anzuzeigen, damit wir sehen können, was wo gelandet ist. Versuchen Sie auch, dies mit dem Simulator zu durchlaufen, und sehen Sie, ob Sie am Ende unbeabsichtigte Orte oder ähnliches ausführen.
Aus dem Schlüsselwort "rom" geht hervor, dass Sie offensichtlich beabsichtigt haben, dass sich dieses Array im Programmspeicher befindet. Stellen Sie wirklich sicher, dass der C-Compiler dies richtig verstanden hat. Ich verwende C18 selten und erinnere mich nicht, was die richtigen Beschwörungsformeln sind, um Konstanten im Programmspeicher zu definieren. Wenn der Compiler es nicht dort abgelegt hat, könnten alle möglichen seltsamen Dinge passieren. Auch hier würde die Linker-Map-Datei dies klären.
Jetzt, da wir eine Linker-Map-Datei haben, können wir das Problem erkennen. 1024 Worte zu je 16 Bit sind 2048 Byte, also 800 h. Es gibt nur einen Abschnitt in der Nähe dieser Größe, und es sind genau 800 h Bytes, also hat der Compiler es verstanden, ihn in den Programmspeicher zu legen. Beachten Sie jedoch, dass es an Adresse 8 platziert ist. Das ist die Interrupt-Vektoradresse mit einfacher oder hoher Priorität. Dieses Array überlappt auch die Interrupt-Adresse mit niedriger Priorität bei 16, so dass Interrupts so oder so nicht mit dem Ort verwendet werden können, an dem dieses Array platziert wurde.
Die Tatsache, dass der Linker das Array dort platziert hat, wo er es getan hat, bedeutet, dass nichts anderes die feste Adresse eines der beiden Interrupt-Vektoren beansprucht. Ich verwende C nicht für Interrupt-Routinen, aber das sagt mir, dass der C-Compiler nicht versteht, dass Ihre Interrupt-Routine tatsächlich eine Interrupt-Routine ist, oder dass sie nicht im Link enthalten war.
Ich weiß nicht, wie Sie das Interrupt-Routine-Modul genannt haben, aber ist es überhaupt in der Link-Map aufgeführt? Wenn ja, dann haben Sie vergessen, die richtige Beschwörung zu murmeln, damit der Compiler weiß, dass es sich um eine Interrupt-Routine handelt, und ihn dadurch zu einer bestimmten Adresse zwingt. Wenn nicht, dann ist es irgendwie nicht im Link enthalten. Dies kann passieren, wenn Sie alle Objektdateien in einer Bibliothek ablegen, damit der Linker auswählen kann, was er möchte, und es keine fehlenden Externals für das Interrupt-Modul gibt. Das kann bei einem Interrupt-Modul passieren, da es nie explizit aufgerufen wird. In diesem Fall muss die Objektdatei des Interrupt-Moduls explizit an den Linker übergeben werden.
Durch Olins Antwort konnte ich das Problem beseitigen.
Wie Olin geschrieben hat, platziert der Linker das Array an der Adresse 0x08. Dies ist die Interrupt-Vektoradresse.
Ein 'Workaround' besteht nun darin, Code explizit an Adresse 0x08 zu platzieren, der zur ISR springt. (Inspiriert von der C18-Bedienungsanleitung Seite 29):
void isr(void);
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm GOTO isr _endasm
}
#pragma code
#pragma interrupt isr
void isr (void)
{
/* ... */
}
oder noch einfacher:
#pragma code high_vector=0x08
#pragma interrupt isr
void isr()
{
/* ... */
}
PetPaulsen
PetPaulsen