Interrupt Handler verbiegen klappt nicht

Nutzen der APIs und allgemeine Coding Fragen
Gnutzi
Beiträge: 6
Registriert: Sa 26. Mär 2016, 16:22

Interrupt Handler verbiegen klappt nicht

Beitrag von Gnutzi » Mo 25. Apr 2016, 06:24

Moin moin,

ich stoße bei verschiedenen Spielereien immer wieder auf das Problem den Interrupt-Handler verbiegen zu müssen.
Dafür definiere ich mit CY_ISR_PROTO(neueFunktion) eine neue Funktion, verbiegen dann in der Main Funktion den Zeiger über ISR_alteFunktion_StartEx(neueFunktion) und kodiere die Funktion dann am Ende des Main.c Files mittels CY_ISR(neueFunktion).
Daran hat der Kompiler nichts auszusetzen und so habe ich es auch mehrfach nachgelesen.
Leider springt aber beim Debuggen der Interrupt dann doch in die automatisch generierte API.
Was mache ich falsch?

Derzeit habe ich das Problem bei dem CY8CKIT-042-BLE Kit mit dem PRoC 4200 BLE Chip und einem kleinen, unausgereiftem Programm.
Habe das mal angehängt.

Ich habe mir C und Mikroprozessoren programmieren selber beigebracht, entschuldigt bitte meinen miserablen Stil.

Gruß Frank
Dateianhänge
Messwagen PRoC.cyprj.Archive01.zip
(749.31 KiB) 148-mal heruntergeladen

Gnutzi
Beiträge: 6
Registriert: Sa 26. Mär 2016, 16:22

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Gnutzi » Mo 25. Apr 2016, 06:55

Moin (schon wieder)

nachdem ich nun eine ganze Weile mit diesem Problem gekämpft habe und nun endlich mal einen Eintrag in diesem Blog wagte..
Habe mir nochmal die Dokumentation zu den Interrupts durchgelesen
http://www.cypress.com/documentation/ap ... interrupts
Und siehe da, in der ISR_Start() API wird der Handler festgelegt.
Das verbiegen mittels ISR_alteFunktion_StartEx(neueFunktion) muss also anstelle der ISR_Start() API erfolgen!
Getan, getestet und funktioniert!
Es ist aber auch schwer bei der Vielzahl der Dokumente immer dasjenige zu finden, dass es so gut beschreibt, wie in der oben genannten :)

Gruß Frank

Reiner W.
Beiträge: 112
Registriert: Di 7. Apr 2015, 11:43

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Reiner W. » Mo 25. Apr 2016, 09:10

Ja, das ist nicht sehr konsistent gelöst. Mittlerweile gibt es ja mindestens 3 verschiedene Möglichkeiten für eigene User ISR.
Ich bleibe eigentlich immer bei der _StartEx() und platziere die vor der main().
Das Verbiegen dann natürlich an Stelle ISR_Start(). Bei größeren Projekten lagere ich das ganze dann komplett aus. Da gibt es in der main() an Stelle der ISR_Start() nur noch ein myModul_init() und im Modul dann die USER_ISR() und der _StartEx() sowie sonstiges init-Geraffel für das Modul. So bleibt main.c einigermaßen klein und aufgeräumt und man kann das Modul recht einfach komplett tauschen.

Gruß Reiner
Reiner W.

Gnutzi
Beiträge: 6
Registriert: Sa 26. Mär 2016, 16:22

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Gnutzi » Mo 25. Apr 2016, 17:43

Hallo Reiner,

beim Auslagern von Funktionen kämpfe ich noch mit diversen Fehlermeldungen, vielleicht sollte man nicht C und C# gleichzeitig lernen?
Aber danke für den Tipp!
Meine Programme werden allmählich größer und Ordnung immer wichtiger.

Eine weiter Variante des Zeigens auf eine ISR Funktion habe ich bei dem CAN-Modul des PSoC 4200M eingesetzt

Code: Alles auswählen

/* Set CAN interrupt handler to local routine */
    CyIntSetVector(CAN_ISR_NUMBER, ISR_CAN);
Zu dem Modul hätte ich aber auch noch mehr Fragen, muss ich nur erst mal ausarbeiten.

Gruß Frank

Reiner W.
Beiträge: 112
Registriert: Di 7. Apr 2015, 11:43

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Reiner W. » Mo 25. Apr 2016, 19:08

beim Auslagern von Funktionen kämpfe ich noch mit diversen Fehlermeldungen, vielleicht sollte man nicht C und C# gleichzeitig lernen?
Kann ich ein Lied von singen;-) Bin auch noch nicht so lange in C unterwegs.
Zu dem Modul hätte ich aber auch noch mehr Fragen, muss ich nur erst mal ausarbeiten.
Nur zu. Wenn ich helfen kann, gerne. Wenn nicht, weis ich, dass hier ja auch noch wirkliche Könner mitlesen. Also einer kann sicher helfen.

Gruß Reiner
Reiner W.

Thomas Barth
Administrator
Beiträge: 89
Registriert: So 5. Apr 2015, 21:46
Wohnort: Frankfurt/M
Kontaktdaten:

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Thomas Barth » Di 26. Apr 2016, 10:31

CY_ISR_PROTO ist ein Makro das nichts anderes macht als einen Prototypen ohne rückgabewert und paramter zu definieren. cpp code
#define CY_ISR_PROTO(FuncName)  void FuncName (void)
ISR_Start setzt den Interrupt Vector auf eine default-funktion <Modul>_Interrupt, welche sich in der <Modul>.c file des Treibers befindet. cpp code
/*******************************************************************************
* Function Name: ISR_Timer1_Start
********************************************************************************
*
* Summary:
*  Set up the interrupt and enable it. This function disables the interrupt, 
*  sets the default interrupt vector, sets the priority from the value in the
*  Design Wide Resources Interrupt Editor, then enables the interrupt to the 
*  interrupt controller.
*
* Parameters:  
*   None
*
* Return:
*   None
*
*******************************************************************************/
void ISR_Timer1_Start(void)
{
    /* For all we know the interrupt is active. */
    ISR_Timer1_Disable();

    /* Set the ISR to point to the ISR_Timer1 Interrupt. */
    ISR_Timer1_SetVector(&ISR_Timer1_Interrupt);

    /* Set the priority. */
    ISR_Timer1_SetPriority((uint8)ISR_Timer1_INTC_PRIOR_NUMBER);

    /* Enable it. */
    ISR_Timer1_Enable();
}
cpp code
/*******************************************************************************
* Function Name: ISR_Timer1_Interrupt
********************************************************************************
*
* Summary:
*   The default Interrupt Service Routine for ISR_Timer1.
*
*   Add custom code between the START and END comments to keep the next version
*   of this file from over-writing your code.
*
*   Note You may use either the default ISR by using this API, or you may define
*   your own separate ISR through ISR_StartEx().
*
* Parameters:  
*   None
*
* Return:
*   None
*
*******************************************************************************/
CY_ISR(ISR_Timer1_Interrupt)
{
    #ifdef ISR_Timer1_INTERRUPT_INTERRUPT_CALLBACK
        ISR_Timer1_Interrupt_InterruptCallback();
    #endif /* ISR_Timer1_INTERRUPT_INTERRUPT_CALLBACK */ 

    /*  Place your Interrupt code here. */
    /* `#START ISR_Timer1_Interrupt` */

    /* `#END` */
}
Der User-Code innerhalb von cpp code
/*  Place your Interrupt code here. */
    /* `#START ISR_Timer1_Interrupt` */

    /* `#END` */
wird auch beim erneuten generieren der API beibehalten.
Alternativ kann man die Function <Modul>_Interrupt_InterruptCallback(); in der cyapicallbacks.h per makro defnieren und mit mit einem symbol <Modul>_INTERRUPT_INTERRUPT_CALLBACK freischalten. Dann mit _Start aktivieren.

ISR_StartEx setzt den Interrupt vector auf den Funktionszeiger der als parameter mitgegeben wird: cpp code
/*******************************************************************************
* Function Name: ISR_Timer1_StartEx
********************************************************************************
*
* Summary:
*  Sets up the interrupt and enables it. This function disables the interrupt,
*  sets the interrupt vector based on the address passed in, sets the priority 
*  from the value in the Design Wide Resources Interrupt Editor, then enables 
*  the interrupt to the interrupt controller.
*  
*  When defining ISR functions, the CY_ISR and CY_ISR_PROTO macros should be 
*  used to provide consistent definition across compilers:
*  
*  Function definition example:
*   CY_ISR(MyISR)
*   {
*   }
*   Function prototype example:
*   CY_ISR_PROTO(MyISR);
*
* Parameters:  
*   address: Address of the ISR to set in the interrupt vector table.
*
* Return:
*   None
*
*******************************************************************************/
void ISR_Timer1_StartEx(cyisraddress address)
{
    /* For all we know the interrupt is active. */
    ISR_Timer1_Disable();

    /* Set the ISR to point to the ISR_Timer1 Interrupt. */
    ISR_Timer1_SetVector(address);

    /* Set the priority. */
    ISR_Timer1_SetPriority((uint8)ISR_Timer1_INTC_PRIOR_NUMBER);

    /* Enable it. */
    ISR_Timer1_Enable();
}
man kann also über CY_ISR_PROTO oder manuell eine Funktion definieren und das System dann über _StartEx scharf machen.

Oder man schreibt seinen code direkt in den Treiber und aktiviert diesen dann über _Start.

Code: Alles auswählen

P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS (TDB.T_ENTIER_16S
                                   ((1.0/C_M_LSB_BH) *
                                   G_M_INFO_DERIVE(T_ALG.E_BH)))

Gnutzi
Beiträge: 6
Registriert: Sa 26. Mär 2016, 16:22

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Gnutzi » So 1. Mai 2016, 09:40

Vielen Dank Thomas für die ausführliche Erläuterung.
Mir hilft es immer sehr, zu wissen warum ich etwas tun muss und nicht nur wie.

Mein Problem mit dem CAN-Modul bei einem PSoC 42000M habe ich, nach euren Antworten, mittlerweile auch für mich gelöst.
Bei dem CAN-Modul kann ich in den Einstellungen auf der TopDesign Seite nur auf alle CAN-IDs reagieren (Basic) oder auf eine bestimmte CAN-ID.
Ich muss aber auf einen bestimmten Teil in der CAN-ID Filtern, der Rest der CAN-IDs variiert.
Zuerst dachte ich, dass es überhaupt nicht geht, fand dann aber folgenden Link mit einer Beschreibung von exakt dem Filter den ich erwartet hatte:
http://www.cypress.com/forum/psoc-3-arc ... fff9%29%3B

Allerdings konnte mit der vorgeschlagenen Lösung nichts anfangen, da die beschriebenen Register nicht gefunden wurden.
Die entsprechenden Kürzel AMR und ACR fand ich aber in der der CAN.h und auch wo sie in der CAN.c beschrieben werden und wenn ich diese dann entsprechend verändere werden die CAN-IDs auch genau so gefiltert wie ich es benötige.
Nur, wenn anschließend irgendwelche Änderungen an der TopDesign Seite gemacht werden, waren meine Einträge wieder futsch.
Jetzt habe ich ein eigenes myCFILE.h und myCFILE.c dafür angelegt,die entsprechenden Funktionen umbenannt und dorthin kopiert.
Sicherlich nicht die eleganteste Lösung aber es funktioniert (und ich verstehe es).

Gruß Frank
Dateianhänge
PSoC CAN Weiche Protoboard 1.cyprj.Archive01.zip
(945.36 KiB) 147-mal heruntergeladen

Reiner W.
Beiträge: 112
Registriert: Di 7. Apr 2015, 11:43

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Reiner W. » Mo 2. Mai 2016, 15:14

Jetzt habe ich ein eigenes myCFILE.h und myCFILE.c dafür angelegt,die entsprechenden Funktionen umbenannt und dorthin kopiert.
Sicherlich nicht die eleganteste Lösung aber es funktioniert (und ich verstehe es).
Mach ich auch so (in ähnlichen Fällen). Die Sachen funktionieren dann (i.R.) auch nach Komponentenupdates. Könnten höchstens obsolet werden, wenn Cypress die Komponente erweitert. Aber dann schadet es auch nicht.
Evtl. kannst du auch nachschauen, ob die Componente für die entsprechende Funktion einen Callback-Möglichkeit vorgesehen hat. Die tröpfeln ja seit Creator V3 so nach und nach in die Komponenten APIs.

Reiner
Reiner W.

Gnutzi
Beiträge: 6
Registriert: Sa 26. Mär 2016, 16:22

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Gnutzi » Mo 2. Mai 2016, 17:31

Hallo Reiner,

danke für deine Antwort, nun bin ich beruhigt!

Die Callbacks hatte ich schon gesehen, hätte aber nicht gedacht, dass sie auch für solche Initialisierungen gedacht sind.
Bei den Interrupt Aufrufen wollte ich sie aber nicht verwenden, um den Interrupt so schlank wie möglich zu halten, außerdem erschien mir die Möglichkeit mit den _StartEx() auch charmanter.
Aber nun werde ich mich da nochmal stärker einlesen.

Gruß Frank

Reiner W.
Beiträge: 112
Registriert: Di 7. Apr 2015, 11:43

Re: Interrupt Handler verbiegen klappt nicht

Beitrag von Reiner W. » Mo 2. Mai 2016, 18:06

erschien mir die Möglichkeit mit den _StartEx() auch charmanter.
Volle Zustimmung.
Außerdem kann ich (bis auf IR) noch keinen roten Faden entdecken, wo Callbecks von der API angeboten werden.

Gruß Reiner
Reiner W.

Antworten