STM32F103 und die Sache mit den NVIC Prioritys

Gast #6631793
Lesenswert?

Moin,

der Code meines Bastelprojektes (GPS Logger für Auto) wächst und wächst 
und leider auch die Probleme. Über die Geschichte mit dem NVIC habe ich 
mir nämlich bisher keine gedanken gemacht und gebe zu, dass ich ihn auch 
nicht wirklich verstehe, was diese Geschichte mit den Prioritäten 
angeht. Ich merke nur, dass die CPU so langsam an ihre Grenzen kommt, 
die LED für den Timer 3 1s Takt wird schon immer unruhiger, weil der 
Interrupt zu oft verdrängt oder unterbrochen wird. DenBetrieb mit 12Mhz 
wegen der Batterieversorgung kann ich jedenfalls vergessen, aktuell 
wieder auf 48Mhz, schluckt gleich 20mA mehr.

Wenn da jetzt noch die SD Karte mit dazu kommt bricht die CPU wohl ganz 
in die Knie :-(

Ich habe an Ints

UART1 9600 baud: Da laufen im 1s Takt ca 200 Bytes NMEA Daten ein und 
lösen RX_NE und RX_IDLE aus. Bytes werden in einen Ringpuffer 
geschaufelt, mehr nicht. Bisher manuell um DMA drücke ich mich noch 
herum, da die Datensätze nicht immer gleich lang sind. 9600baud kosten 
jedenfalls ne Menge CPU Zeit

RTC: 1s Takt mit Unix Time um die Uhrzeit zu berechnen mit localtime.

Timer 3: 1/10s Takt: Alle 0,5s liest er über I2c den ADXL345 aus, dauert 
genau 0,5ms das Auslesen der paar Bytes. 1/10s brauche ich für LED 
Blitzen.

Systick: 1/1000 Sekunde, das Teil brauche ich eigentlich gar nicht, ich 
benutze den DWT Timer der Debug Unit als Zeitbasis.

Prio 1 muss die UART haben, da sollte nix verloren gehen.
RTC ist eher unwichtig, die zählt eh allein weiter, auf ne Sekunde kommt 
es nicht an

Timer 3: Wichtig! 0,5s sind ein erprobtes Raster für die 
Bewegungserkennung.

Könnte sich vielleicht der A.K. mal erbarmen da Licht hinein zu bringen, 
die ich die Prios der Teile setzen muss? Setze ich die Prio des I2C Ints 
auf 15 kommt der jedenfalls kaum mehr zum Zuge. Auf 0 immer aber dann 
fehlen Bytes in den UART Sätzen.
1
SysTick_Config(RCC_Clocks.SYSCLK_Frequency/1000);    // Systick für 1ms
2
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
1
  /* Interruptanbindung an den NVIC */
2
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
3
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
4
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
5
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6
    NVIC_Init(&NVIC_InitStructure);
7

8
    /* Pending Ints löschen */
9
    USART_ClearITPendingBit(USART1,USART_IT_IDLE);
10
    USART_ClearITPendingBit(USART1,USART_IT_RXNE);
11

12
    /* Ints aktivieren */
13
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);       /* RXNE Interrupt */
14
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);       /* RX Idle Interrupt */
1
 /* ----- 1s RTC Interrupt an NVIC koppeln --------*/
2
   NVIC_InitTypeDef NVIC_InitStructure;
3
   NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
4
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
5
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
6
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
7
   NVIC_Init(&NVIC_InitStructure);
1
 /* Interrupt Handler anbinden */
2
   nvicStructure.NVIC_IRQChannel = TIM3_IRQn;
3
   nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;  
4
   nvicStructure.NVIC_IRQChannelSubPriority = 0;
5
   nvicStructure.NVIC_IRQChannelCmd = ENABLE;
6
   NVIC_Init(&nvicStructure);
Beitrag #6631799 wurde von einem Moderator gelöscht.
#6631810
Lesenswert?

MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in
> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung

C-hater bist dus?

Christian J. schrieb:
> 9600baud kosten
> jedenfalls ne Menge CPU Zeit

Nein, weil er nur bei einem empfangenen Byte einen IRQ auslöst während 
des Empfangens kann die CPU anderes tun.

Die Prios sind relativ straight forward, je niedriger die Nummer desto 
mehr Priorität, sprich höher priorisierte IRQ können andere IRQ 
unterbrechen.

Alles in allem hast du nichts was den µC wirklich an die Grenze bringt, 
das ist alles mehr als human. Ich würde sagen das du irgendwo anders ein 
Problem hast.
Gast #6631813
Lesenswert?

Kevin M. schrieb:
> Alles in allem hast du nichts was den µC wirklich an die Grenze bringt,
> das ist alles mehr als human. Ich würde sagen das du irgendwo anders ein
> Problem hast.

Nee, sieht grad wüst aus auf dem Schreibtisch. u-center für die GPS 
Konfig und den F103 am Debugger in der IDE. Ich habe testweise mal das 
UART_IT_ORE Flag (Overrun) auf ne LED gelegt. Ist schon so, dass der 
UART Int den Timer 3 voll platt macht, da kommen 3 NMEA Sätze a 82 Bytes 
in einem Rutsch. Habe in jedem Int halt ne LED angesteuert, da sieht man 
das ganz gut.

Gefühlt kann es natürlich sein, dass der UART int deutlich öfter gefired 
wird als ich es sehe. Das Teil hat ja ne Menge Bits im NVIC.

Die ChanFat hängt auch am Systick mit dran bei 1/1000, die braucht das 
scheinbar. Und die RTC brauche ich für die Zeitstempel der Dateien. Ist 
aber noch nicht aktiviert alles.

Setze ich den Timer 3 auf Prio High geht trotzdem kein Byte mehr 
verloren, wenn ich die Baudrate auf 4800 zurücknehme. Das reicht total 
aus. Bei 9600 leider sind einige rote LED Blinker dabei.

Ich werde spasseshalber die Sache trotzdem auf DMA umschreiben. Aber 
heute nicht mehr .... gähn...
Gast #6631816
Lesenswert?

MaWin schrieb im Beitrag #6631799:

> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in
> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung

Wer's mit einem STM32 @12MHz nicht gebacken bekommt, schafft's auch 
nicht mit einem AVR8 @8MHz.

Nö, man muss nicht die Hardware wechseln, sondern den Programmierer.

Im Übrigen: Einen ATtiny13 würde ich ganz sicher nicht nehmen, wenn die 
Aufgabe ist, über UART, I2C und SPI zu kommunizieren und dabei mit wenig 
Energie auszukommen, allerdings ganz sicher auch keinen STM32F103.

Dafür würde ich einen ATtiny814 nehmen. Und, na klar: Assembler.
Gast #6631892
Lesenswert?

Harry L. schrieb:
> Dann sind deine UART-Routinen absoluter Murks.
>
> Zeig doch mal!

PS: I2C dauert 0,5ms... am Logger gemessen, 6 Bytes holen bei 200khz 
Takt.
1
void Init_UART1() {
2

3
    USART_InitTypeDef usart1_init_struct;
4
    GPIO_InitTypeDef gpioa_init_struct;
5
    NVIC_InitTypeDef NVIC_InitStructure;
6

7
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO |
8
                           RCC_APB2Periph_GPIOA, ENABLE);
9

10
    /* GPIOA PA9(TX) / PA10(RX) alternative function */
11
    gpioa_init_struct.GPIO_Pin = GPIO_Pin_9;
12
    gpioa_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
13
    gpioa_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
14
    GPIO_Init(GPIOA, &gpioa_init_struct);
15

16
    gpioa_init_struct.GPIO_Pin = GPIO_Pin_10;
17
    gpioa_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
18
    gpioa_init_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
19
    GPIO_Init(GPIOA, &gpioa_init_struct);
20

21
    /* Baud rate 9600, 8-bit data, One stop bit
22
     * No parity, Tx, No HW flow control */
23

24
    usart1_init_struct.USART_BaudRate   = 9600;
25
    usart1_init_struct.USART_WordLength = USART_WordLength_8b;
26
    usart1_init_struct.USART_StopBits   = USART_StopBits_1;
27
    usart1_init_struct.USART_Parity     = USART_Parity_No ;
28
    usart1_init_struct.USART_Mode       = USART_Mode_Rx | USART_Mode_Tx;
29
    usart1_init_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
30
    USART_Init(USART1, &usart1_init_struct);
31

32
    /* Interruptanbindung an den NVIC */
33
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
34
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
35
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
36
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
37
    NVIC_Init(&NVIC_InitStructure);
38

39
    /* Pending Ints löschen */
40
    USART_ClearITPendingBit(USART1,USART_IT_IDLE);
41
    USART_ClearITPendingBit(USART1,USART_IT_RXNE);
42

43
    /* Ints aktivieren */
44
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);       /* RXNE Interrupt */
45
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);       /* RX Idle Interrupt */
46
    USART_ITConfig(USART1, USART_IT_ORE, ENABLE);       /* RX Idle Interrupt */
47

48
    USART_Cmd(USART1, ENABLE);
49
    NVIC_EnableIRQ(USART1_IRQn);
50
    //NVIC_DisableIRQ(USART1_IRQn);
51
}

und
1
/* UART1 Interrupt Service Routine */
2
void USART1_IRQHandler() {
3

4
    /* Neues Byte wurde empfangen vom GPS Modul */
5
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
6
    {
7
       gpsbuf[rx_ptr] = USART_ReceiveData(USART1);
8
       rx_ptr = (rx_ptr +1 ) % BUFSIZE;
9
       SetLED(GELB,ENABLE);
10

11
       /* ------------------------------------------ */
12
       USART_ClearITPendingBit(USART1, USART_IT_RXNE);
13
    }
14

15
    /* Timeout, letztes Byte wurde empfangen */
16
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
17
    {
18
       rx_ptr = 0; /* Reset RX Pointer */
19
       SetLED(GELB,DISABLE);
20
       SetLED(BLAU,DISABLE);
21

22
       /* ------------------------------------------ */
23
       USART_ClearITPendingBit(USART1, USART_IT_IDLE);
24
    }
25

26
    if(USART_GetITStatus(USART1, USART_IT_ORE) != RESET)
27
    {
28
        SetLED(BLAU,ENABLE);
29
        USART_ClearITPendingBit(USART1, USART_IT_ORE);
30
    }
31
}

I2C
1
void TIM3_IRQHandler()
2
{
3
    #define RELOADDIV 5
4
    _Bool fMovement = false;
5
    static adxl345_t oldval;
6
    static uint8_t Divider1s = RELOADDIV;
7
    static uint8_t Divider3s = 3*RELOADDIV;
8

9
    /* Andere IRQ Anforderungen ausblenden */
10
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) == RESET)
11
       return;
12

13
    /* ------ 0.5s Takt Durchlauf ----- */
14
    if (!(--Divider1s))
15
    {
16
        /* Neue Werte auslesen */
17
        oldval = adxl345;
18
        if (ADXL345_Read())
19
            SetBoardLED(ENABLE);
20
        else {
21
            /* Clear IRQ Flag */
22
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
23
            return;
24
        }
25

26
        /* Mit den alten Werten vergleichen */
27
        if (((abs(oldval.x - adxl345.x) >= 4) ||
28
            (abs(oldval.y - adxl345.y) >= 4)  ||
29
            (abs(oldval.z - adxl345.z) >= 4)))
30
        {
31
            fMovement = true;
32
            MoveCounter = 0;
33
        } else {
34
            if (MoveCounter < TIMEOUT_MOVE)
35
                MoveCounter++;
36
            fMovement = false;
37
        }
38

39
        SetLED(ROT,fMovement);
40
        SetLED(GELB,(MoveCounter>=TIMEOUT_MOVE));
41

42
        Divider1s = RELOADDIV;
43
    }
44
    else
45
        SetBoardLED(DISABLE);
46

47
    /* 3s Gültiges GPS Signal liegt an */
48
    if (fValidGPS) {
49
        if (!(--Divider3s)) {
50
        /* 1s Takt Durchlauf */
51
            SetLED(BLAU,ENABLE);
52
            Divider3s = 3*RELOADDIV;
53
        } else
54
            SetLED(BLAU,DISABLE);
55
    } else
56
        SetLED(BLAU,DISABLE);
57

58
    /* ------------------------------------ */
59

60
    /* Clear IRQ Flag */
61
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
62
}
Beitrag #6631926 wurde von einem Moderator gelöscht.
Gast #6631940
Lesenswert?

Christian J. schrieb:
> Ich werde spasseshalber die Sache trotzdem auf DMA umschreiben. Aber
> heute nicht mehr .... gähn...

Herr lass Hirn regnen. Wem ein UART Interrupt bei 9600baud aus der Bahn 
wirft, der sollte ernsthaft anfangen über seinen Code nachzudenken und 
nicht über die Taktfrequenz der CPU...

Einen Punkt soll/muss man aber noch abprüfen. Manche Interupts können 
mehrfach ausgelöst werden, wenn die Interuptroutine so früh verlassen 
wird, dass das Reseten der Flags in der Peripherie noch nicht angekommen 
ist. Das ist eine Stolperfalle bei der die AVR Jünger häufig vom Glauben 
abfallen, aber sie existiert.
Gast #6632045
Lesenswert?

Christian J. schrieb:
> Wenn da jetzt noch die SD Karte mit dazu kommt bricht die CPU wohl ganz
> in die Knie

Wenn du eine SD Karte intensiv nutzt, brauchst du dir um die 
Stromaufnahme des Mikrocontroller keine Gedanken mehr machen, weil die 
SD Karte mehr brauchen wird. Da sind Werte um 200mA durchaus normal.

Die Auflistung deiner Interrupts klingt nach wenig Last. Untersuche mal, 
wo dein Programm die meiste Zeit verbringt, vermutlich in Wartschleifen 
für I/O.

Du könntest jeder ISR einen Ausgang zuweisen, denn du am Anfang auf High 
und am Ende wieder auf Low setzt. An diese Ausgänge schließt du dann 
einen Logic Analyzer oder ein Oszilloskop an, dann siehst du sofort, wo 
die meiste Zeit drauf geht.
Gast #6632076
Lesenswert?

Matthias S. schrieb:

> Aber bei 9600 Baud für den USART kommt gerade mal ein IRQ jede ms
> (1,04ms). Das sollte soviel Luft nach oben lassen, das man die ISR in
> der Priorität auch runtersetzen kann.

So wie sich das darstellt wird der Int ununterbrochen aufgerufen bis das 
IDLE kommt. Da stimmt nochwas nicht. Es kann echt sein, dass da das 
gleiche Problem auftaucht, wie vor einigen Monaten mal mit dem Togglen 
von Pins: Set und Reset liefen im Debugger durch aber nicht mehr in der 
optimierten Release Version. Nicht, weil der Code wegoptimiert wurde, 
was wegen der volatile Dekl. aller Register eh nicht passiert sondern 
weil das Set gar nicht ankam und sofort vom reset plattgemacht wurde. 
Ich habe damals Befehle wie _DMB etc eingefügt, die dafür wohl gemacht 
worden sind.

Checke das heute abend mal mit einem Counter in der ISR.... 9600 sind 
echt nicht viel, so ein blöder Arduino packt ja schon 115.000.
Gast #6632086
Lesenswert?

Stefan ⛄ F. schrieb:
> Die Auflistung deiner Interrupts klingt nach wenig Last. Untersuche mal,
> wo dein Programm die meiste Zeit verbringt, vermutlich in Wartschleifen
> für I/O.
>
> Du könntest jeder ISR einen Ausgang zuweisen, denn du am Anfang auf High
> und am Ende wieder auf Low setzt. An diese Ausgänge schließt du dann
> einen Logic Analyzer oder ein Oszilloskop an, dann siehst du sofort, wo
> die meiste Zeit drauf geht.

Stefan, Du bist echt die Sonne dieses Forums! Einfach mal ein Lob für 
deine fundierten Antworten und auch deine klasse Webseite, die zu meinen 
Stammseiten gehört neben der von Diller.

Bevor ich hier frage studiere ich natürlich fremden Code im Netz. Leider 
sind auch diese Code of sehr fehlerhaft, und sei es nur UART1 in der 
Init aber UART3 als ISR... da fragt man sich schon ob derjenige das 
jemals am Laufen hatte oder einfach nur kompiliert und hochgeladen.

Viele ISR haben am Anfang, so wie meine Timer 3 einen Müllsammler. Raus 
bei allen False Positives und nur rein bei meinen INTS. Das erinnert 
mich etwas daran Arrays 1 größer als nötig zu machen... nur als Vorsicht 
damit man bloss die Grenzen nicht überschreitet. for;i<x; i++... ist i 
nun als letztes x-1 oder x? Oder doch sogar x+1?

Default sind ja alle Ints deaktiviert aber trotzdem scheine sich einige 
nicht darauf zu verlassen.
Gast #6632112
Lesenswert?

user934394 schrieb:
> Effizienter gehts kaum noch ...

Kenne ich, habe einiges vom dem benutzt früher, vor allem Grafik für den 
F429 Disco. Tolle Ausarbeitung über die Uart und DMA. Aber auch sehr 
viele Fälle, die es zu berücksichtigen gilt. Ich versuche es erstmal 
selbst ohne DMA und halte es klein. Verstehe dafür alles und laufe in 
jede Falle selbst rein.
Gast #6632124
Lesenswert?

m.n. schrieb:
> Das taucht wiederholt in der ISR auf, wobei es am Ende der ISR voll
> daneben ist. Deine TIM3-ISR ruft unbekannte Funktionen auf und ist ganz
> schlecht strukturiert.

Was genau stört da? Es wird ein I2C Leseprozess aufgerufen und ein paar 
LEDs.
Zudem ein paar RETFI mit Flag Bereinigung. Hätte auch if-then-else draus 
machen können. RETFI ist aber nicht unüblich. Packt der Compiler.
Zeit genug ist dafür da. Klar, kannste auch im Main die Lesungen machen, 
wenn ein Flag gesetzt wird vom  Ints, viele Wege führen nach ROM. I2C 
kann beliebig unterbrochen werden.

Darüber hinaus wird jeder INT, der nicht ein Reload ist sofort 
rausgeworfen. (könnte ja sein...) Und am Ende lösche ich das Pending 
Flag... sehe da jetzt die Bäume nicht. Und was ist da "ganz schlecht"? 
ISR die Peripherie auslesen sind ja keine Seltenheit.

Kläre mich mal auf.
Gast #6632134
Lesenswert?

Christian J. schrieb:
> Moin,
>
> der Code meines Bastelprojektes (GPS Logger für Auto) wächst und wächst
> und leider auch die Probleme. Über die Geschichte mit dem NVIC habe ich
> mir nämlich bisher keine gedanken gemacht und gebe zu, dass ich ihn auch
> nicht wirklich verstehe, was diese Geschichte mit den Prioritäten
> angeht. Ich merke nur, dass die CPU so langsam an ihre Grenzen kommt,
> die LED für den Timer 3 1s Takt wird schon immer unruhiger, weil der
> Interrupt zu oft verdrängt oder unterbrochen wird. DenBetrieb mit 12Mhz
> wegen der Batterieversorgung kann ich jedenfalls vergessen, aktuell
> wieder auf 48Mhz, schluckt gleich 20mA mehr.

Wenn der Stromverbrauch ein Problem werden sollte, dann kannst Du Dir da 
recht einfach Erleichterung verschaffen:
Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als 
xxxPill.

Der 411 nimmt bei 100MHz weniger als die Hälfte des Stroms auf, den ein 
103 bei 72MHz aufnimmt.
Gast #6632135
Lesenswert?

Christian J. schrieb:
> Was genau stört da? Kläre mich mal auf.

http://stefanfrings.de/stm32/stm32f1.html#ivektoren

"Innerhalb der ISR muss man das Flag auch zurück setzen, aber ein 
bisschen früher als ganz zum Schluss!"

Weil sonst die nächste Flanke nicht mehr zuverlässig erkannt wird. Denn 
bis der zurücksetzen-Befehl im Interruptcontroller ankommt, dauert es 
ein paar Takte.
Gast #6632142
Lesenswert?

Dr. MCU schrieb:
> Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als
> xxxPill.

https://blog.adafruit.com/2021/03/05/new-product-stm32f411-blackpill-development-board

Seufz.... bloss gibt es für den keine StdPeriph Libs mehr, da die schon 
total veraltet sind. Alles nur noch mit HAL... und für Hobby... naja, 
der Umstieg ist nicht so die Welt, ich schreibe oft HAL Sachen fix um, 
liest sich ja vieles sehr gleich.

Der Druck wächst... hoffe die neue EmBitz 2.0 Version wird die HAL mit 
drin haben, bisher muss man die manuell dazu fügen und auch CMSIS 
austauschen. Ich frickel das auch manuell zusammen, da die eingebaute 
SPL nicht die letzte ist, die es gab.
Gast #6632147
Lesenswert?

Stefan ⛄ F. schrieb:
> Weil sonst die nächste Flanke nicht mehr zuverlässig erkannt wird. Denn
> bis der zurücksetzen-Befehl im Interruptcontroller ankommt, dauert es
> ein paar Takte.

Weist du zufällig, ob man da mit dem Data Memory Barrier Befehlen 
weiterkommen könnte? Die sind ja sehr tief in der Hardware wirksam, zu 
tief für jemanden, der nicht mit dem Teil ins Bett geht.
Gast #6632156
Lesenswert?

Christian J. schrieb:
> Weist du zufällig, ob man da mit dem Data Memory Barrier Befehlen
> weiterkommen könnte?

Sie wurden mir damals empfohlen, als ich das Problem hatte, dass Flanken 
nicht erkannt wurden und dadurch die ganze Kommunikation stecken blieb.

Ich habe sie aber nicht ausprobiert, sondern mich an Beispielen von ST 
orientiert, wo die Flags immer echt früh in der ISR zurück gesetzt 
werden.
Gast #6632158
Lesenswert?

Christian J. schrieb:
> Gefühlt kann es natürlich sein, dass der UART int deutlich öfter gefired
> wird als ich es sehe. Das Teil hat ja ne Menge Bits im NVIC.

Wie sich Interrupts "gefühlt" verhalten ist irrelevant. Wichtig ist, was 
wirklich passiert ;-)

Es wurde bereits der Weg über einen IO angesprochen, der beim Eintritt / 
Verlassen der ISR toggelt. Ein Debugger sollte das aber auch ohne den 
Umweg über einen GPIO können, sofern man beim STM32F103 SWD+SWO als 
Debug-Interface nutzt.

Stichwort: Timeline, bzw. Interrupt Log

z.B.
https://www.iar.com/knowledge/learn/debugging/interrupt-logging/
https://www.segger.com/products/development-tools/systemview/

SystemView scheint eine Instrumentierung des Codes zu benötigen aber 
eventuell gibt es auch eine Alternative von Segger, die Interrupts und 
deren Timing ohne zusätzlichen Code zeigt. Hier könnte Til S. 
wahrscheinlich mehr Licht ins Dunkel bringen...

Gruß,
Michael
Moderator Persönliche Seite #6632244
Lesenswert?

Christian J. schrieb:
> Dr. MCU schrieb:
>
>> Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als
>> xxxPill.
>
> 
https://blog.adafruit.com/2021/03/05/new-product-stm32f411-blackpill-development-board
> Seufz.... bloss gibt es für den keine StdPeriph Libs mehr, da die schon
> total veraltet sind.

Stimmt überhaupt nicht. Die 401er und 411er arbeiten hervorragend mit 
den StdPeriph Libs aus Embitz 1.x.

Beispiel: WordClock mit WS2812. Diese SW arbeitet sowohl mit 
STM32F103, STM32F401 und STM32F411. Alles kompiliert mit EmBitz.

Übrigens findest Du in der SW auch UART-Treiber, für die auch 115200 Bd 
auch ein Kinderspiel sind. Fifos sind selbstverständlich integriert.
Gast #6632251
Lesenswert?

MaWin schrieb im Beitrag #6631799:

> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in
> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung

Was soll das, Mustermann? Jetzt auch noch als MaWin posieren geht nun 
wirklich zu weit. Keiner glaubt, dass MaWin so blöd ist.
(Firma: SEGGER) #6632330
Lesenswert?

Michael F. schrieb:
> SystemView scheint eine Instrumentierung des Codes zu benötigen aber
> eventuell gibt es auch eine Alternative von Segger, die Interrupts und
> deren Timing ohne zusätzlichen Code zeigt. Hier könnte Til S.
> wahrscheinlich mehr Licht ins Dunkel bringen...

Ja, richtig, für SystemView muss der Code instrumentiert sein was aber 
jetzt nicht das Problem sein sollte. Das embOS ist zum Beispiel bereits 
instrumentiert, so das in der Timeline alle embOS API Aufrufe und 
Interrupts sichtbar sind. Wäre eine Überlegung embOS in dem Projekt 
einzusetzen. Das vereinfacht die ganzen Timing Probleme weil man 
Aufgaben in Tasks oder Software Timer auslagern kann.

Ansonsten bin ich da eher old school und benutze auch gerne Port Pins 
und das Oszilloskop.

Der NVIC des Cortex-M mit den ganzen Prioritäten kann schon verwirrend 
sein aber ist eigentlich nicht so kompliziert. Dazu gibt es haufenweise 
gute Artikel online.
Gast #6632339
Lesenswert?

MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen
> und in
> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung

Full ACK, nur dass ich einen Atmega8 nehmen würde.
Gast #6632505
Lesenswert?

Ok, das Problem dürfte gefunden sein:

Keine 2s Sekunden nach Start zeigte ein volatile Zähler 32 Bit im UART 
ISR diesen Wert an, der schoss nur so hoch.

Ok, haben wir was zu suchen.... kein Wunder dass die CPU für nichts 
anderes mehr Zeit hat.

PS: Übeltäter ist die Sektion für UART_RX_IDLE, die wird dauernd 
angesprungen, RX und ORE normal, bzw. letzteress gar nicht. Kaum enabled 
geht es schon los und bleibt auch auf Dauerfeuer.

https://community.st.com/s/question/0D50X00009XkfxzSAB/idle-interrupt-on-stm32f0-fires-when-enabling-it

Gibt noch sehr viel mehr über dieses Problem.
Angehängte Dateien:
Gast #6632554
Lesenswert?

Ok, erledigt, alles klappt jetzt. Für die Nachwelt.. sind wohl schon 
etliche drauf reingefallen.

Da fast alle anderen Bits dieses Registers auch so gelöscht werden 
klappt es auch mit den beiden Readout am Ende der Routine. Lässt man die 
restlichen 3 Zeilen weg klappt es immer noch. Denn ClearPendingBit hat 
nur wenige zulässige Flags und die sind es nicht. Mein Fehler, wieder 
was im Netz abgeschrieben ohne es geprüft zu haben :-(

    USART1->SR;
    USART1->DR;
    USART_ClearITPendingBit(USART1, USART_IT_IDLE);
    USART_ClearITPendingBit(USART1, USART_IT_ORE_RX);
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
Angehängte Dateien:
Gast #6632575
Lesenswert?

PS: Bevor ich es vergesse: Ich reagiere grundsätzlich nicht mehr auf 
"Gastkommentare", da diese fast immer zu 99% Müll sind, lese sie nicht 
einmal mehr. Nicht unhöflich gemeint, nur halt Mülltrennung.
Gast #6632585
Lesenswert?

Christian J. schrieb:

> PS: Bevor ich es vergesse: Ich reagiere grundsätzlich nicht mehr auf
> "Gastkommentare", da diese fast immer zu 99% Müll sind, lese sie nicht
> einmal mehr. Nicht unhöflich gemeint, nur halt Mülltrennung.

So what. Andere (weniger zur Realitätsverweigerung veranlagte) lesen es.

Und nehmen dann vielleicht tatsächlich den ATtiny814 (oder besser 1614, 
wenn SD-Cards in's Spiel kommen). Und stellen fest: absolut kein Problem 
und viel weniger Energiebedarf als ein STM32F103...

Sogar schon in C und erst recht in Assembler...

Soviel zum Thema: 99% Müll...

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