Wie initialisiere ich bei XMC47 und PlatformIO die Interrupts

OP (Firma: private) #8087426
Lesenswert?

Ja geanu, das. Das kann ich kompilieren und flaschen. Das Resultat ist rote LED1 leuchtet. Sie blinkt aber nicht.

[env:xmc4700] platform = infineonxmc board = xmc4700_relax_kit framework = arduino monitor_speed = 115200

Das ist mein main.cpp File:

#include <XMC4700.h> #include "xmc_ccu4.h" #include "xmc_gpio.h" #include "xmc_scu.h"

#define CALCULATE_PERIOD(interval_in_ms) ((35155 * interval_in_ms) / 1000) /* fCPU=144MHz; Prescaler set to 4096 */

// Globale Variable für Timer-Interrupt volatile bool timerInterruptOccurred = false;

// Globale Variable für die Timer-Periode uint32_t timer_interval = 1000;

// Deklaration des Interrupt-Handlers für CCU43-Slice 1 extern "C" void CCU43_1_IRQHandler(void); extern "C" void UserIRQHandler(void);

int main(void) { bool button_edge = true;

/* INITIALIZE CCU43 FOR TOGGLING OF LED / / Initialize CCU43 / XMC_CCU4_Init(CCU43, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR); / Enable the clock for selected timer */ XMC_CCU4_EnableClock(CCU43, 3);

/* Prepare configuration / XMC_CCU4_SLICE_COMPARE_CONFIG_t slice_config = { / .tc = / 0, / .prescaler_initval = / 12, / set pre-scaler to 4096 / / .float_limit = / 0, / .dither_limit = / 0, / .passive_level = / 0, / .timer_concatenation = / 0 }; / Configure the timer / XMC_CCU4_SLICE_CompareInit(CCU43_CC43, &slice_config); / programs the timer period register according to time interval value / XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC43, CALCULATE_PERIOD(timer_interval)); / Transfers value from shadow timer registers to actual timer registers / XMC_CCU4_EnableShadowTransfer(CCU43, XMC_CCU4_SHADOW_TRANSFER_SLICE_3 | XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_3); / Bind period match event to an NVIC node CCU43_1_IRQn / XMC_CCU4_SLICE_SetInterruptNode(CCU43_CC43, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU4_SLICE_SR_ID_1); / Enables timer(period match) event */ XMC_CCU4_SLICE_EnableEvent(CCU43_CC43, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);

XMC_CCU4_SLICE_ClearTimer(CCU43_CC43); XMC_CCU4_SLICE_StartTimer(CCU43_CC43);

// NVIC-Konfiguration: Priorität setzen und Interrupt aktivieren NVIC_SetPriority(CCU43_1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 63, 0)); NVIC_EnableIRQ(CCU43_1_IRQn);

/* INITIALIZE LED1 ON PORT 5.9 FOR OUTPUT (PUSH-PULL) */ XMC_GPIO_SetMode(P5_9, XMC_GPIO_MODE_OUTPUT_PUSH_PULL);

/* INITIALIZE BUTTON1 ON PORT 15.13 FOR INPUT */ XMC_GPIO_SetMode(P15_13, XMC_GPIO_MODE_INPUT_TRISTATE); XMC_GPIO_EnableDigitalInput(P15_13);

/* INITIALIZE BUTTON2 ON PORT 15.12 FOR INPUT */ XMC_GPIO_SetMode(P15_12, XMC_GPIO_MODE_INPUT_TRISTATE); XMC_GPIO_EnableDigitalInput(P15_12);

while(1U) { /* any button pushed?/ if (!XMC_GPIO_GetInput(P15_13) || !XMC_GPIO_GetInput(P15_12)) { / new edge on any button? / if (button_edge == true) { / which button ? / if (!XMC_GPIO_GetInput(P15_13)) { / Button1 pushed. Decrease cycle time of flashing LED. / timer_interval = (timer_interval > 100) ? (timer_interval - 100) : timer_interval; } else { / Button2 pushed. Increase cycle time of flashing LED. / timer_interval = (timer_interval < 1500) ? (timer_interval + 100) : timer_interval; } XMC_CCU4_SLICE_StopTimer(CCU43_CC43); XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC43, CALCULATE_PERIOD(timer_interval)); XMC_CCU4_EnableShadowTransfer(CCU43, XMC_CCU4_SHADOW_TRANSFER_SLICE_3 | XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_3); XMC_CCU4_SLICE_StartTimer(CCU43_CC43); } button_edge = false; } else { / currently no button pushed / / next trigger on button is new edge */ button_edge = true; }

1
}

}

// Interrupt-Service-Routine für CCU43-Slice 1 void CCU43_1_IRQHandler(void) { // Prüfen, ob der Perioden-Match-Interrupt ausgelöst wurde if (XMC_CCU4_SLICE_GetEvent(CCU43_CC43, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH)) { // Interrupt-Flag löschen XMC_CCU4_SLICE_ClearEvent(CCU43_CC43, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);

1
// LED-Zustand umschalten
2
XMC_GPIO_ToggleOutput(P5_9);

} }

void UserIRQHandler(void) {

XMC_GPIO_ToggleOutput(P5_9); }

: Bearbeitet durch User
#8087511
Lesenswert?

Du hast die LED so angeschlossen, dass sie bereits vor dem ersten Interrupt an geht richtig? Falls ja:

Ich würde nachschauen, ob das Arduino Framework eine ISR für den Timer enthält und nach der Vektor Tabelle suchen um den Namen deiner ISR zu kontrollieren.

Falls nein: Eventuell ist irgendwas innerhalb der ISR ist fehlerhaft, so dass sie nur einmal getriggert wird obwohl der Timer läuft.

Ob er läuft, kannst du mit dem Debugger kontrollieren. Vermutlich läuft er nicht, denn in dem falsch formatierten Wirrwarr von Source-Code und Kommentaren scheint mir die Initialisierung des Timers auskommentiert zu sein.

: Bearbeitet durch User
#8087528
Lesenswert?

Ich habe das XMCLib Blink Beispiel von Infineon geholt

Von wo?

Ich habe diesen Quelltext vom XMC Arduino Core gefunden https://github.com/Infineon/XMC-for-Arduino Ist das der, den du verwendest?

Ich habe deinen Quelltext manuell restauriert und lesbar gemacht. Siehe Anhang. Er wirft einige Fragen auf:

Zeile 7: Warum kommen in der Formel weder die 144 MHz noch der Prescaler 4096 vor? Magische Zahlen wie 35155 gehören da nicht hin.

Zeilen 32-63: Du hast die ganze Konfiguration des Timers auskommentiert!

Zeile 33-47: Warum hast du hast die Namen der struct Members auskommentiert? Jetzt musst man das manuell mit der Definition vergleichen: https://github.com/Infineon/XMC-for-Arduino/blob/d7ff35bd48260264a30c775c651b7b061b8f7ad8/cores/xmc/xmc_lib/XMCLib/inc/xmc_ccu4.h#L616

Zeilen 18 und 134: Wozu dient der UserIRQHandler? Habe dazu keine Doku gefunden, außer irgendwas für das DAVE Framework. So kann sie auch nicht funktionieren, da sie den Interrupt nicht im Timer quittiert.

Du findest die Namen der ISR in der Datei https://github.com/Infineon/XMC-for-Arduino/blob/master/variants/XMC4700/startup_XMC4700.S Den CCU43_1_IRQHandler gibt es dort, aber keinen UserIRQHandler.

Zeilen 87-93: In der Hauptschleife fragst du zuerst ab, ob irgendein Taster gedrückt wurde, und dann fragst du die selben Ports nochmal ab, um zu erkennen welche gedrückt wurde. Bis dahin kann der Taster aber schon wieder losgelassen sein. Er kann auch prellen. Es würde wesentlich zuverlässiger funktionieren, wenn du die Ports pro Schleifendurchlauf nur einmal in Variablen einliest und dann die folgenden if-Bedingungen auf diese Variablen zugreifen.

Ob du den Timer überhaupt richtig benutzt kann ich mangels Erfahrung mit XMC nicht sagen. Wie gesagt würde ich mit dem Debugger kontrollieren, ob er überhaupt läuft. Dass müsste man ja am Counter Register sehen können. Die Doku findest du dort: https://www.infineon.com/assets/row/public/documents/30/42/infineon-ccu4-xmc1000-xmc4000-ap32287-an-en.pdf?fileId=5546d4624e765da5014ed8dd0f4614c0

Angehängte Dateien:
: Bearbeitet durch User
OP (Firma: private) #8087549
Lesenswert?

Danke für Eure Unterstützung. Es lagt nicht daran, dass der Timer nicht lieft. Er lief, ich konnte es im Debugger erkennn. Die C Struktur slice_config hat Infineon geändert. Sie war falsch initialisiert. Der Link zu Capture Comp are Unit 4 (CCU4 )A P 3 2 2 8 7 war Gold wert. Ich habe die Member auskommentiert, weil ich noch 2024 g++ verwende, der nur den Dialekt C++17 versteht. Da ist ist eine gezielte Memberinitialisierung noch nicht möglich. Herzlichen Dank nochmals, hat mir viel Zeit gespart.

Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren