Forum: Mikrocontroller und Digitale Elektronik PIC32 SPI2 Interrupt Probleme (1xx_2xx Serie)


von Daniel W. (danielwohlmuth)


Lesenswert?

Hallo zusammen,

habe mir gedacht ich poste mal ein Problem, dessen Lösung mich gestern 
Nacht fast um den Schlaf gebracht hat.
Problematik: SPI2 auf dem PIC32 der 1xx oder 2xx Serie in Kombination 
mit dem XC32 Compiler und der SPI Lib.

Wenn man nun versucht auf dem SPI2 einen Interrupt mit folgenden 
Funktionsaufrufen zu bekommen... Geht nicht. Beim SPI1 funktioniert das, 
wenn man genau die selben Funktionsaufrufe durchführt.
1
...
2
3
SpiChnOpenEx(SPI_CHANNEL2, c1, c2, div);
4
5
//Enable SPI2 interrupt.
6
INTSetVectorPriority(INT_SPI_2_VECTOR, INT_PRIORITY_LEVEL_3);
7
INTSetVectorSubPriority(INT_SPI_2_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
8
INTEnable(INT_SPI2, INT_ENABLED);
9
10
SpiChnPutC(SPI_CHANNEL2, 0); //starte transfer
11
12
...

soweit so gut, Ende vom Lied:
Ich habe gemerkt, dass in der "int_1xx_2xx.h" des compilers die 
kompletten Makros für den SPI2 fehlen. Dementsprechend werden sie 
vermutlich auch nicht hinter den "INTSetVector..." Funktionsaufrufen 
implementiert sein.
Habe also nun die Makros per Hand eingepflegt und sie anschließend statt 
der Compilerfunktionen aufgerufen.

Hier die erweiterten Makros
1
#ifdef _SPI2
2
#define mSPI2EClearIntFlag()                (IFS1CLR = _IFS1_SPI2EIF_MASK)
3
#define mSPI2EGetIntFlag()                  (IFS1bits.SPI2EIF)
4
#define mSPI2EGetIntEnable()                (IEC1bits.SPI2EIE)
5
#define mSPI2EIntEnable(enable)             (IEC1CLR = _IEC1_SPI2EIE_MASK, IEC1SET = ((enable) << _IEC1_SPI2EIE_POSITION))
6
/*********************************************************************
7
 * SPI 2 Transfer
8
 ********************************************************************/
9
#define mSPI2TXClearIntFlag()               (IFS1CLR = _IFS1_SPI2TXIF_MASK)
10
#define mSPI2TXGetIntFlag()                 (IFS1bits.SPI2TXIF)
11
#define mSPI2TXGetIntEnable()               (IEC1bits.SPI2TXIE)
12
#define mSPI2TXIntEnable(enable)             (IEC1CLR = _IEC1_SPI2TXIE_MASK, IEC1SET = ((enable) << _IEC1_SPI2TXIE_POSITION))
13
/*********************************************************************
14
 * SPI 2 Receive
15
 ********************************************************************/
16
#define mSPI2RXClearIntFlag()               (IFS1CLR = _IFS1_SPI2RXIF_MASK)
17
#define mSPI2RXGetIntFlag()                 (IFS1bits.SPI2RXIF)
18
#define mSPI2RXGetIntEnable()               (IEC1bits.SPI2RXIE)
19
#define mSPI2RXIntEnable(enable)             (IEC1CLR = _IEC1_SPI2RXIE_MASK, IEC1SET = ((enable) << _IEC1_SPI2RXIE_POSITION))
20
/*********************************************************************
21
 * SPI 2 Vector
22
 ********************************************************************/
23
#define mSPI2ClearAllIntFlags()              ( IFS1CLR = (_IFS1_SPI2EIF_MASK | _IFS1_SPI2TXIF_MASK | _IFS1_SPI2RXIF_MASK))
24
#define mSPI2IntDisable()                    ( IEC1CLR = (_IEC1_SPI2EIE_MASK | _IEC1_SPI2TXIE_MASK | _IEC1_SPI2RXIE_MASK))
25
#define mSPI2SetIntEnable(flags)       ( IEC1SET = (((flags) & 0x7) << _IEC1_SPI2EIE_POSITION))
26
#define mSPI2SetIntPriority(priority)        (IPC9CLR = _IPC9_SPI2IP_MASK, IPC9SET = ((priority) << _IPC9_SPI2IP_POSITION))
27
#define mSPI2GetIntPriority()                (IPC9bits.SPI2IP)
28
#define mSPI2SetIntSubPriority(subPriority)  (IPC9CLR = _IPC9_SPI2IS_MASK, IPC9SET = ((subPriority) << _IPC9_SPI2IS_POSITION))
29
#define mSPI2GetIntSubPriority()             (IPC9bits.SPI2IS)
30
#endif


Aufruf für TX Interrupt dann so:
1
...
2
3
SpiChnOpenEx(SPI_CHANNEL2, c1, c2, div);
4
5
//Enable SPI2 interrupt.
6
mSPI2SetIntPriority(3);
7
mSPI2SetIntSubPriority(0)
8
mSPI2TXIntEnable(1);
9
10
SpiChnPutC(SPI_CHANNEL2, 0); //starte transfer
11
12
...


Falls jemand eine Erklärung dafür hat wäre ich dankbar, habe auch mal 
Microchip geschrieben, ob es einen Grund für die fehlenden defines gibt, 
oder ob ich es einfach nicht überrissen habe, die lib richtig zu 
benutzen :)
Naja, falls jemand vor dem selben Problem steht, oben der WorkAround.
Liebe Grüße,
Daniel

von Stampede (Gast)


Lesenswert?

Danke. Am besten noch ein Support Ticket an Microchip damit das behoben 
wird.

von Frank B. (foobar)


Lesenswert?

Also ich kann das Problem nicht reproduzieren. Wenn ich
1
INTSetVectorPriority(INT_VECTOR_SPI(SPI_CHANNEL2), INT_PRIORITY_LEVEL_3)
aufrufe (das Macro "INT_VECTOR_SPI" liefert dasselbe Ergebnis, wie wenn 
man INT_SPI_2_VECTOR direkt angibt), dann wird die Interruptroutine 
aufgerufen, die wie folgt definiert ist:
1
void __ISR(_SPI_2_VECTOR,ipl3) _SPI2Handler(void)
Verwende ich z.B. INT_PRIORITY_LEVEL_4 im INTSetVectorPriority-Aufruf, 
mit derselben Interruptroutine, dann wird die Interruptroutine nicht 
aufgerufen.

Ich habe hier MPLAB X V2.00 installiert. Eine Verifizierung des 
Source-Codes bestätigt auch, daß es funktionieren sollte: in "c:\program 
files 
(x86)\Microchip\xc32\v1.31\pic32-libs\peripheral\int\source\int_tbl_lib_ 
obs.c"  ist ein __IntTbl-Array definiert, wo alle SPI2-Register und 
Flags definiert sind und was von INTSetVectorPriority in int_tbl_lib.c 
verwendet wird. Die m*-Macros werden dort nicht gebraucht. Kann 
natürlich nicht schaden, die auch zu haben, wenn man mal low-level 
darauf zugreifen möchte.

Gibt es eigentlich eine vernünftige Dokumentation? Der Link "Peripheral 
Library Guide" im Startmenü unter "Microchip->MPLAB C32" ist kaputt. Ich 
habe im Internet ein PDF gefunden, aber da fehlen einige Funktionen und 
Beispiele, die man in den Header-Dateien sehen kann. Ist immer etwas 
mühselig, sich die Header-Dateien, Beispielcodes und Google-Ergebnisse 
durchlesen zu müssen, um irgendetwas machen zu können.

von Daniel W. (danielwohlmuth)


Lesenswert?

Ich verwende den XC32 nicht den normalen C32, kann sein, dass es da 
richtig implementiert ist.
Dass die Interrupt Routine nicht aufgerufen wird, wenn Priorität vom 
Interrupt ( INT_PRIORITY_LEVEL_4 ) und Priorität der 
__ISR(_SPI_2_VECTOR,ipl3 "<--" ) nicht übereinstimmt ist normal.

Dokumentationen sind allesamt rar vorhanden von seitens des Herstellers.
Die Hilfe im MPlab X ist allerdings ganz gut soweit. Unter dem 
jeweiligen Reiter des Compilers findet man die Funktionen und auch 
Beispiele der Libs. Wenn man Glück hat auch brauchbare :)

Schöne Grüße

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.