Hallo, ich arbeite mit Embitz und debugge mich grad durch meine Funkanwendung. Soweit so gut, die Daten kommen auch rein aber seltsamerweise hängt sich die CPU dann irgendwie auf. D.h. Breakpoints im Hauptprogramm werden nicht mehr erkannt aber die Interrupts die LEDs blinken lasse laufen munter weiter. Im Debug Mode lässt sich das Problem soweit einkreisen, wie im Bild zu sehen. D.h. dsas Funkmodul hat gültige Daten empfangen, es wurde ein INT ausgelöst und die CPU holt sich diese rein. Tippe ich mich bis zum Ende durch ist bei der Klammer Schluss, danach ist er "weg". Kein gelber Balken mehr, keine Reaktion auf Breakpoints. Callstack stimmt aber soweit. Ich habe beim Linken übrigens LTO eigeschaltet, benutze die Nano Lib. Kennt das jemand? Gruss, Christian
Den Interrupt Handler hast du ordnungsgemäß zurückgesetzt?! Die Komplette ISR zur Posten wäre eventuell Sinnvoll. ;-)
DraconiX schrieb: > Den Interrupt Handler hast du ordnungsgemäß zurückgesetzt?! Den Interrupt Handler kann man nicht zurücksetzen. Allenfalls kann und sollte man ein Interrupt Flag zurücksetzen wenn es gesetzt wurde.
Aruinoquäler schrieb: > DraconiX schrieb: > Den Interrupt Handler hast du ordnungsgemäß zurückgesetzt?! > > Den Interrupt Handler kann man nicht zurücksetzen. Allenfalls > kann und sollte man ein Interrupt Flag zurücksetzen wenn es > gesetzt wurde. Ja gut, dann halt im Interrupt-Handler die Interrupt-Flag zurück gesetzt. :-D Und ja, wenn ein Int ausgelöst wurde, wurde die Flag ja auch sicherlich gesetzt. Gibt es denn beim STM32 ein Interrupt der ausgelöst werden kann, welcher nicht zurück gesetzt werden muss? Ist mir bis dato noch nicht übern Weg gelaufen, wäre aber Interessant zu wissen.
Ich kapier es nicht! In der for Schleife landet er im HardFault Handler! Das war doch vorher nicht.... /* Startet die RTC */ void Init_RTC() { volatile uint32_t i; /* Enable PWR and BKP clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* LSI clock stabilization time */ for(i=0;i<5000;i++);
DraconiX schrieb: > Den Interrupt Handler hast du ordnungsgemäß zurückgesetzt?! Die > Komplette ISR zur Posten wäre eventuell Sinnvoll. ;-) Ähm...... Den setze ich nicht zurück, der soll ja zur Laufzeit umgebogen sein. Ich setze nur die INT Flags zurück..... Problem ist: Das Laufzeitverhalten ist anders als wenn ich rum debugge. Mein Master sendet 150 Datensätze, die stehen beim "Run" im Debug Mode auch alle fein im Array of struct drin, läuft nichts über etc. Alle 3 Timer lösen ihren Int aus, der RTC Int auch, die Dimmung über die PWM Outsputs läuft auch.... setze ich einen roten Break Punkt klebt er sofort da dran. aber er ist aus main while (1) {...} einfach raus. Da kommt er gar nicht mehr hin. Der Stop Knopf zum Pausieren geht nicht mehr, da passiert gar nichts mehr. Habe testweise mal die Libs verändert, nehme ich die Link Time Optimization raus schmiert er mit hardFault ganz ab. Hier die Int Routine:
1 | /* ====================== Interrupt Handler RF Modul ============================*/
|
2 | |
3 | void IRQ_ROUTINE(void) |
4 | {
|
5 | |
6 | static uint8_t tcnt = 0; |
7 | |
8 | if(EXTI_GetITStatus(IRQ_LINE)!=RESET) |
9 | {
|
10 | // ISR Code.....
|
11 | if (RF_DataReady()) |
12 | {
|
13 | SetRedLED(ENABLE); |
14 | // RF_CE_Enable(ENABLE); // TEST & FIXXXME !!!!
|
15 | |
16 | /* In welcher Pipe sind Daten? */
|
17 | uint8_t pipe = RF_GetFilledPipe(); |
18 | /* Wie viele Bytes sind da ?*/
|
19 | uint8_t nrBytes = RF_GetPayloadSize(); |
20 | |
21 | if ((pipe == 1) && (nrBytes <= sizeof(actual_data))) |
22 | {
|
23 | f_RF_Timeout = false; |
24 | ReceivedDataBlocks++; |
25 | |
26 | /* Daten auslesen */
|
27 | RF_ReadPayload((uint8_t*)&actual_data,nrBytes); |
28 | |
29 | if (actual_data.Feuchte_Now > 90) |
30 | actual_data.Feuchte_Now = 100; |
31 | |
32 | /* ----- Sind es historische Daten? ------------ */
|
33 | // Sind es historische Daten?
|
34 | if (actual_data.command == RX_CMD_HISTORY) |
35 | {
|
36 | // Neue Daten in Historie kopieren
|
37 | uint8_t index = actual_data.nrDataSet; |
38 | if (index <= HISTORY_MAX_IDX) |
39 | {
|
40 | /* Zeit gelegentlich neu setzen */
|
41 | if (++tcnt >= 60) { |
42 | Set_NewTime(actual_data.unix); |
43 | tcnt = 0; |
44 | }
|
45 | /* Daten aus Struct einsortieren usw */
|
46 | Manage_RF_Data(index); |
47 | f_GotData = true; |
48 | }
|
49 | }
|
50 | |
51 | /* ----- Sind es Daten für das E2PROM ? --------- */
|
52 | // ......
|
53 | }
|
54 | |
55 | /* Fifo löschen, egal was noch drin war */
|
56 | RF_FlushRX(); |
57 | RF_ClearStatus(); |
58 | RF_CE_Enable(ENABLE); |
59 | |
60 | SetRedLED(DISABLE); |
61 | }
|
62 | |
63 | EXTI_ClearITPendingBit(IRQ_LINE); // Remove LINE interrupt flag bit |
64 | }
|
65 | }
|
Und hier der Init des Handlers für externe Pin Interrupst an GPIO A2. DMA des AD Wandlers spielt auch noch munter weiter.
1 | void RF_Init_Handler() |
2 | {
|
3 | |
4 | /* PC1 Interrupt Pin konfigurieren auf Line 0 EXTI0_IRQn für Funbkmodul
|
5 | |
6 | Line 0-4 haben einen eigenen Handler, 5-9 haben den Gleichen
|
7 | und 10-15 ebenfalls. Alle Px0 sind auf Line 0 angebunden usw.
|
8 | |
9 | EXTI0_IRQn EXTI0_IRQHandler Handler for pins connected to line 0
|
10 | EXTI1_IRQn EXTI1_IRQHandler Handler for pins connected to line 1
|
11 | EXTI2_IRQn EXTI2_IRQHandler Handler for pins connected to line 2
|
12 | EXTI3_IRQn EXTI3_IRQHandler Handler for pins connected to line 3
|
13 | EXTI4_IRQn EXTI4_IRQHandler Handler for pins connected to line 4
|
14 | EXTI9_5_IRQn EXTI9_5_IRQHandler Handler for pins connected to line 5 to 9
|
15 | EXTI15_10_IRQn EXTI15_10_IRQHandler Handler for pins connected to line 10 to 15
|
16 | |
17 | */
|
18 | |
19 | GPIO_InitTypeDef GPIO_InitStruct; |
20 | EXTI_InitTypeDef EXTI_InitStruct; |
21 | NVIC_InitTypeDef NVIC_InitStruct; |
22 | |
23 | if (!spi_initialized) |
24 | RF_Init_SPI(); |
25 | |
26 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); |
27 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); |
28 | |
29 | /* PA2 als Input */
|
30 | GPIO_StructInit (&GPIO_InitStruct); |
31 | GPIO_InitStruct.GPIO_Pin = IRQ_PIN; |
32 | GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; |
33 | GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; |
34 | GPIO_Init(IRQ_PORT, &GPIO_InitStruct); |
35 | |
36 | // Line einem Port und Pin zuordnen, hier Port A, Pin 2 = PA2
|
37 | GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource2); |
38 | |
39 | /* Line 2 der External IRQs 2 konfigurieren */
|
40 | EXTI_InitStruct.EXTI_Line = IRQ_LINE; /* PA2 ist verbunden mit EXTI_Line2 */ |
41 | EXTI_InitStruct.EXTI_LineCmd = ENABLE; /* Enable interrupt */ |
42 | EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; /* Interrupt mode */ |
43 | EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; /* Trigger auf fallende Flanke */ |
44 | EXTI_Init(&EXTI_InitStruct); /* Aktivieren und zu EXTI hinzufügen */ |
45 | |
46 | /* NVIC einbinden: PA2 ist auf EXTI_Line1 und hat den Vector EXT2_IRQn */
|
47 | NVIC_InitStruct.NVIC_IRQChannel = IRQ_HDL; |
48 | NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; /* Höchste Priorität */ |
49 | NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; /* Sub Priorität */ |
50 | NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; /* Enable Interrupt */ |
51 | NVIC_Init(&NVIC_InitStruct); /* Zum NVIC hinzufügen */ |
52 | |
53 | NVIC_EnableIRQ(IRQ_HDL); /* Interrupt ein */ |
54 | |
55 | }
|
Setz halt einen Brechpunkt in den Hardfaulthandler... Dann kannst du dich mit den Moeglichkeiten beschaeftigen, aus dem dort vorgefundenen Zustand auf den Fehler zu schliessen.
(º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· schrieb im Beitrag #5105152: > Dann kannst du dich mit den Moeglichkeiten beschaeftigen, > aus dem dort vorgefundenen Zustand auf den Fehler zu > schliessen. Das lasse ich dann doch lieber sein, da ich mir dabei schon mal einen abgebrochen habe. Bisher hat eine Umschreibung mancher Probleme auf eine andere Art geholfen. Oder halt nested Interrupts verbieten, das eleminiert auch schon viele Fehler. Wenn ich das unten auskommentiere ist das problem weg. Also ist da was strubbelig und sobald ich einen kaffee fertig habe geht die Nachtschicht weiter. Habe ja Urlaub und das Wetter ist mies :-)
1 | // Neue Daten in Historie kopieren
|
2 | uint8_t index = actual_data.nrDataSet; |
3 | if (index <= HISTORY_MAX_IDX) |
4 | {
|
5 | /* Zeit gelegentlich neu setzen */
|
6 | // if (++tcnt >= 60) {
|
7 | // Set_NewTime(actual_data.unix);
|
8 | // tcnt = 0;
|
9 | // }
|
10 | /* Daten aus Struct einsortieren usw */
|
11 | // Manage_RF_Data(index);
|
PS: Da liegt der Wurm drin... aber bisher lief die beanstandungsfrei
1 | /* Zeit neu einstellen, läuft allein weiter per RTC ISR */
|
2 | void Set_NewTime(uint32_t newtime) |
3 | {
|
4 | /* Unix Zeit für localtime casten */
|
5 | time_t value = (time_t)newtime; |
6 | |
7 | /* Interne RTC auf Masterstation sychronisieren */
|
8 | RTC_SetCounter(value); |
9 | |
10 | /* Unixzeit umwandeln */
|
11 | struct tm *ptr = localtime(&value); |
12 | |
13 | /* Zeit atomar in eigenen Struct holen */
|
14 | NVIC_DisableIRQ(RTC_IRQn); |
15 | memcpy((void*)&mytime,ptr,sizeof(struct tm)); // mytime <- localtime Buffer |
16 | NVIC_EnableIRQ(RTC_IRQn); |
17 | }
|
Einen Brechpunkt im Hardfaulthandler zu setzen ist nun keine Raketenwissenschaft. Von TI gibt es eine recht informative Appnote wie Mann mit den Informationen im Hardfault umgeht: http://www.ti.com/lit/pdf/SPMA043 Da das alles ARM Systemregister sind, gilt das was dort steht ohne Einschraenkungen auch fuer den M3 von ST (von der Driverlib im ROM mal abgesehen...). Aus der Appnote: "The Stellaris Cortex-M processor provides a powerful fault handling system and several features to help you find the cause of a fault. After debugging a few faults, you will be more comfortable handling and troubleshooting faults as they happen, and will be able to find the cause in a few minutes." Denk mal drueber nach!
(º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· schrieb im Beitrag #5105189: > Einen Brechpunkt im Hardfaulthandler zu setzen ist nun keine > Raketenwissenschaft. Ich werde es mir mal anschauen, damals habe ich aber nur Bahnhof verstanden vor gut 1 Jahr. Dazu braucht man ja erstmal einen Einstieg und anschliessend "den Blick für das Wesentliche" um die Urache zu finden. Einen hardFault Handler schreiben ist easy, der Roohbau ist ja schon fertig. PS: Habs! Auch ohne den Hardfault: Diese Set_NewTime Routine rief localtime auf. Allerdings hatte ich in dieser die RTC Ints nicht abgeschaltet, so dass immer mal einer dazwischen haute. Die Routine ist nicht reentrant. Dachte der Compiler merkt das. Jetzt sind die aus und erstmal läuft es :-)
Zum Hardfault Handler, da setzt man einen Breakpoint, greift sich den SP und guckt nach, was an der Adresse SP+24 steht. Das ist nämlich die Adresse, an der die Exception ausgelöst wurde. Dann greift man sich das Mapfile und guckt, in welcher Funktion das ist. Oder man ist bequem und lädt die Firmware per Debugger und klickt sich dann zu der Adresse vor, dann sieht man auch gleich die Quelltextzeile.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.