Forum: Mikrocontroller und Digitale Elektronik STM32F1 Timer Problem


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jojo S. (Gast)


Angehängte Dateien:

Lesenswert?

Ich hatte die IRMP Software für die mbed Bibliothek angepasst. Auf einem 
LPC1347 und 4088 funktioniert das auch gut, dann wollte ich das auch auf 
einem STM32F1 testen. Das Ergebnis war negativ obwohl ich ja nur 
Basisfunktionen benutze. Bei der Fehlersuche bin ich auf einen bekannten 
Issue gestossen: In IRMP wird mit 15 kHz die Samplingroutine aufgerufen 
und das geht in mbed einfach mit einem 'Ticker' Objekt. Da fügt man mit 
attach_us(&prog, period) eine Funktion einer Liste hinzu die dann mit 
period_time [µs] aufgerufen wird. Der Listenteil ist quasi 'HighLevel' 
und für alle MCUs gleich. Die Implentierung des Timer/Interrupthandlings 
ist LowLevel und dann MCU abhängig.
Die LPC haben 32 Bit Timer und da ist der LowLevel Teil recht einfach 
und performant, beim STM32F1 wird ein 16 Bit Timer benutzt und über 
einen 'SlaveCounter' auf 32 Bit erweitert. Hier liegt mMn der 
Knackpunkt, das ist nicht richtig Interruptfest. Nach einigen 100 ms bis 
s (abhängig von der Periodenzeit) entstehen 65 ms Pausen in denen der 
Ticker hängt.
Gefühlsmässig würde ich sagen das ist sehr schwer bis unmöglich sauber 
in Software zu lösen, falls doch, wie?
Oder kann man beim STM32F1 Timer kaskadieren um einen echten 32 Bit 
Zähler zu erhalten?
Ich habe schon lange in dem Code herumgestochert, falls da jemand mit 
reinsehen möchte ist hier die Funktion wie ich sie interpretiere:

- in us_ticker.c ist in us_ticker_read() das Aulesen des Timers und 
erweitern auf 32 Bit. Wenn hier ein 16 Bit Überlauf passiert wird (soll) 
die Inkosistenz abgefangen.
in us_ticker_set_interrupt(timestamp_t timestamp) wird die neue 
CompareMatch Zeit berechnet und gesetzt. Dazu wird das Delta zur 
aktuellen Zeit berechnet und kontrolliert ob das noch innerhalb des 
Timerüberlaufs passiert. Wenn die Zeit > 65ms ist wird in oc_int_part 
n*65 ms gesetzt.

- in hal_tick.c ist die TimerInit und IRQ.
Bei Timerüberlauf wird der Slave inkrementiert.
Bei Compare Match wird der User-IRQ aufgerufen wenn keine n * 65 ms zu 
warten ist, sonst wird die restliche Wartezeit berechnet und gesetzt.
Die eigentlich Rechnerei sieht ok aus, nur wenn der Timer kurz vor dem 
Überlaufen ist klappt das mit dem SlaveCounter scheinbar nicht.

us_ticker_c:
https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32F1/us_ticker.c

hal_tick.c:
https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/hal_tick.c

das gemeldete Issue:
https://github.com/mbedmicro/mbed/issues/816

im Anhang sieht man die 65 ms Aussetzer im Ausgangssignal.
Mein Beispielprogramm sieht so aus:
1
#include <mbed.h>
2
3
4
Ticker ticker;
5
DigitalOut led1(PC_13);
6
DigitalOut led2(PB_12);
7
8
void flip() {
9
    led2 = !led2; 
10
}
11
12
int main() 
13
{
14
    ticker.attach_us(&flip, 200); // the address of the function to be attached (flip) and the interval (x microseconds)
15
16
    // spin in a main loop. flipper will interrupt it to call flip
17
    while(1) {
18
      led1 = !led1;
19
      wait(0.1);
20
    }
21
}

Ich weiss das ist nicht alles einfach nachzuvollziehen, aber die Zahl 
der STM32 Experten wächst hier ja.

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.