Forum: Mikrocontroller und Digitale Elektronik Fujitsu 16fx Relolad Timer Grundsatzfrage


von Sebastian L. (sebastian_l)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

wir sind gerade dabei, uns in den 16FX / MB96340 von Fujitsu 
einzuarbeiten und auch gleich eine Frage.

- Der Prozessor läuft bei 16MHz.
- Wir haben einen Reload-Timer (RLT1), der auf 12,5 uSekunden gesetzt 
ist und einen Interrupt auslöst.
- Gleichzeitig haben wir einen Free-Running-Timer, den wir zur 
Zeitmessung einsetzen (mit Überlauferkennung).
- Als dritten haben wir noch einen weiteren Reload-Timer (RLT0), der 
ebenfalls einen Interrupt auslöst; RLT0 wird nur für UART-Ausgaben 
benutzt und läuft alle 100ms.

In dem Interrupt von RLT1 wird als erstes eine Zeitmessung vorgenommen 
(Zeit die seit dem letzen IRQ RLT1 verstrichen ist) - das Ergebnis wird 
gespeichert und dann in RLT0 ausgegeben.

Soweit klappt´s ganz gut mit einigen kleinen Abweichungen bei der 
Zeitmessung.

Ziel der Routine in RLT1 ist die generierung diverser PWM Signale mit 
vorheriger Ansteuerung von bis zu 7 Latches - diese Sachen sind im 
Moment noch NICHT implementiert. Es geht zunächst nur um ein Signal an 
PDR07_P0. Aber aus diesem Grund ist der Vergleich "L0_P0_Cnt" drin.
Das zu erzeugende Signal ist im Moment auch egal (ebenfalls, dass es 
sicherlich einfachere Möglichkeiten gibt PPG, etc.).

Meine Frage ist nun - wenn ich den mit "Block 1" (siehe unten) 
gekennzeichneten Block nicht drin habe, bekomme ich als Ergebnis 12,5 
uSekunden für das Aufruf-Intervall RLT1. Sobald Block 1 drin ist, jedoch 
bereits 25 uSekunden.

Verbrauchen so wenige Befehle aus "Block 1" (1 Division, 2 Vergleiche, 
1-2 Variablen setzen, Variable erhöhen und Portausgabe) bereits mehr als 
12,5 uSekunden, so dass ein Interrupt "verschluckt" wird ???

Habe die Main.c auch mal angehängt.

Tut mir leid, es ist eher eine Grundsatzfrage - aber das sind die 
wichtigsten ;-) Ich kann mir nicht vorstellen, dass der uC so viel Zeit 
für so ein paar Befehle vernichtet !? Oder doch!?

Danke,
Sebastian


---


__interrupt void RLT1_LatchTimer_IRQ (void)
{
  // Zeitintervall seit letzem Aufruf

  FRT0_Count = TCDT0;
  FRT0_ovl1_cnt_func = FRT0_ovl1_cnt;      // Save current FRT value
  Ticks=abs(FRT0_ovl1_cnt_func - FRT0_ovl1_cnt_old) * 0x10000UL + 
FRT0_Count - FRT0_Count_old;
  FRT0_ovl1_cnt_old = FRT0_ovl1_cnt_func;  // Save current FRT value as 
reference for next cycle
  FRT0_Count_old = FRT0_Count;
  flag_ticks_valid=1;

  // ------------- BLOCK 1 START -------------
  helper_RLT1 = 10000;  // per Definition - "Teiler" 10 kHz
    if (L0_P0_Cnt>=(helper_RLT1 / L0_P0_Hz)) {
      // Zeit für einen Flankenwechsel
      // bestehender Wert kann nicht ausgelesen werden, sonst
      // würden wir den Wert aus dem letzten Latch bekommen!
      if (L0_Memory.bit.P00 == 1) {
        L0_Memory.bit.P00 = 0;
      } else {
        L0_Memory.bit.P00 = 1;
      }
      // Jetzt den Counter zurücksetzen
      // geht beides, 1. "sauberer" (kein Überspringen möglich)
      // 2. einfacher & schneller.
      // L0_P0_Cnt=L0_P0_Cnt-(helper_RLT1 / L0_P0_Hz);
      L0_P0_Cnt=0;
    }
    L0_P0_Cnt++;

    // Daten anlegen
    PDR07 = L0_Memory.byte;
  // ------------- BLOCK 1 ENDE -------------


TMCSR1_UF = 0;        // reset underflow interrupt request flag
return;

}

von Sebastian L. (sebastian_l)


Lesenswert?

Hallo nochmal,

hat niemand eine Idee ode einen Tip dazu ?
Oder habe ich das ganze zu umständlich geschildert ?

Grüße,
Sebastian

von Lakai (Gast)


Lesenswert?

Hi,

ich fürchte, die Long-Multiplikation verbraucht bereits viel Zeit. Du 
hast in deiner ISR rund 190 Zyklen bis zum nächsten IRQ Zeit. Bei einer 
Long-Multiplikation muß auf die interne Bibliothek zurückgegriffen 
werden, da die 16LX-CPU keine Instruktion dafür hat. Diese Funktion 
braucht rund 150 Zyklen. Kommt nun noch die Multiplikation im "Block 1" 
hinzu, war's das dann. 16 MHz sind halt nicht so ultra-flott.

Gruß.

von Sebastian L. (sebastian_l)


Lesenswert?

Hallo zusammen,

ich habe mich heute nochmal an das Problem rangesetzt und versucht, das 
ganze zu lösen. Ist mir soweit auch gelungen, ich hätte nur ganz gerne 
Feedback, ob jemand in den Routinen noch Probleme und/oder 
Verbesserungsmöglichkeiten gibt.

Ziel war, sowohl die 32bit Variable als auch die Multiplikation zu 
vermeiden:
1
Ticks=abs(FRT0_ovl1_cnt_func - FRT0_ovl1_cnt_old) * 0x10000UL +
2
FRT0_Count - FRT0_Count_old;

Ich habe folgendes gemacht (Kommentare habe ich zum besseren Verständnis 
drin gelassen):
1
// Init:
2
// timerOvl=4272, timerCnt=34480;
3
// FRT0_ovl: aktueller Overflow Wert des Free-Running Timers
4
// FRT0_cnt: aktueller Wert des Free-Running Timers
5
// FRT0_ovl_old: vorheriger Overflow Wert des Free-Running Timers
6
// FRT0_cnt_old: vorheriger Wert des Free-Running Timers
7
8
// Zunächst Differenzen ovl/cnt zu letztem Durchlauf bestimmen
9
// und in diff_ovl und diff_cnt speichern.
10
diff_ovl=FRT0_ovl-FRT0_ovl_old;
11
// folgt OF@Subtraktion bei diff_cnt?
12
if (FRT0_cnt<FRT0_cnt_old) diff_ovl--;
13
diff_cnt=FRT0_cnt-FRT0_cnt_old;
14
15
// Timer dezimieren
16
// folgt OFSubtraktion bei @timerOvl?
17
if (timerOvl<diff_ovl) {
18
  // wenn ja, ist der Timer abgelaufen. 
19
  timerOvl=diff_ovl;
20
}
21
timerOvl-=diff_ovl;
22
// folgt OF@SubtraktionCNT?
23
if (timerCnt<diff_cnt) {
24
  if (timerOvl==0) {
25
    timerCnt=diff_cnt;
26
  } else {
27
    timerOvl--;
28
  }
29
}
30
timerCnt-=diff_cnt;
31
32
if ((timerCnt==0) && (timerOvl==0)) {
33
  Uart_SendString(0, "test-Counter expired.\n"); 
34
  // Reload values.
35
  // bereits "überschrittene" Zeit findet keine beachtung
36
  timerOvl=4272; timerCnt=34480;
37
}
38
39
FRT0_ovl_old = FRT0_ovl;  
40
FRT0_cnt_old = FRT0_cnt;

Gibt´s eine bessere Lösung und/oder Verbessungsvorschläge ?

Danke,
Sebastian

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.