Forum: Mikrocontroller und Digitale Elektronik STM32F103 und die Sache mit den NVIC Prioritys


von Christian J. (Gast)


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.
von Kevin M. (arduinolover)


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.

von Christian J. (Gast)


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...

von Harry L. (mysth)


Lesenswert?

Christian J. schrieb:
> 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.

Dann sind deine UART-Routinen absoluter Murks.

Zeig doch mal!

9600 Baud ist selbst bei Dauerfeuer wirklich nix, was einen F103 ins 
Schwitzen bringen könnte. (Wenn man es richtig macht)

von c-hater (Gast)


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.

von Deudsch Leera (Gast)


Lesenswert?

c-hater schrieb:
> Nö, man muss nicht die Hardware wechseln, sondern den Programmierer.

Auch schon deswegen weil er Prioritys nicht korrekt schreiben kann.

von A. B. (funky)


Lesenswert?

"dauert genau 0,5ms das Auslesen der paar Bytes."

Zeig mal deine Routinen. Wenn es 0,5ms am Stück dauert und du da 
irgendwo wartest/Zeit verbrätst dann hast du schon dein Problem gefunden

von Christian J. (Gast)


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.
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Christian J. schrieb:
> if (ADXL345_Read())
>             SetBoardLED(ENABLE);

Langsame I2C Komm im Timer 3 IRQ Handler ist sicher keine gute Idee.

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.

von temp (Gast)


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.

von Stefan F. (Gast)


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.

von Christian J. (Gast)


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.

von Christian J. (Gast)


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.

von user934394 (Gast)


Lesenswert?

Bzgl. UART, DMA und variabler Länge der Nachrichten:
https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

Effizienter gehts kaum noch ...

von Stefan F. (Gast)


Lesenswert?

Christian J. schrieb:
> Das erinnert mich etwas daran Arrays 1 größer als nötig zu machen

Ich sage mal so: Wenn du zu viele Daten in ein Array schreibst, dann 
können das durchaus auch mehr als 1 Byte sein. Dagegen kann dich die 
Programmiersprache C nicht schützen.

von Christian J. (Gast)


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.

von m.n. (Gast)


Lesenswert?

Christian J. schrieb:
> /* Clear IRQ Flag */
>     TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
> }

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.
Da kann man keine Laufzeit abschätzen.

von Christian J. (Gast)


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.

von Dr. MCU (Gast)


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.

von Stefan F. (Gast)


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.

von Christian J. (Gast)


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.

von Christian J. (Gast)


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.

von Stefan F. (Gast)


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.

von Michael F. (Firma: IAR Systems) (michael_iar)


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

von Frank M. (ukw) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Bastian (Gast)


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.

von Til S. (Firma: SEGGER) (til_s)


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.

von m.n. (Gast)


Lesenswert?

Bastian schrieb:
> Keiner glaubt, dass MaWin so blöd ist.

Ich schon.

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

von Megaler (Gast)


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.

von Christian J. (Gast)


Lesenswert?

m.n. schrieb:
> __ISB();

Instruction Synchronization Barrier flushes the pipeline in the 
processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed

Und damit läuft das Moped?

von c-hater (Gast)


Lesenswert?

Christian J. schrieb:
> m.n. schrieb:
>> __ISB();
>
> Und damit läuft das Moped?

Na klar. Du brauchst das nur an möglichst vielen, beliebig gewählten 
Stellen im Code einzusetzen.

LOL

von Christian J. (Gast)


Angehängte Dateien:

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.

von Christian J. (Gast)


Angehängte Dateien:

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);

von c-hater (Gast)


Lesenswert?

Christian J. schrieb:

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

Tja, es hat schon Vorteile, das DB eines µC zu lesen, bevor man ihn 
verwendet. Das gilt völlig unabhängig vom konkreten µC...

von Christian J. (Gast)


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.

von c-hater (Gast)


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...

von Megaler (Gast)


Lesenswert?

c-hater schrieb:
> Assembler

Hihi. Er hat Assembler gesagt!

von m.n. (Gast)


Lesenswert?

Christian J. schrieb:
> Nicht unhöflich gemeint, nur halt Mülltrennung.

Ganz schön unverschämt!
Zur Müllvermeidung solltest Du hier besser keine Fragen mehr stellen.

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.