www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt latency - kleiner 4us MSP430F1612


Autor: Andreas H. (msp430-fan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich möchte mit meinem MSP430F1612 alle 2us den Port 6.1-6.7 einlesen und 
in einen Buffer schreiben (Triggerung mit Interrupt an Port 2.1). Der 
MSP430 läuft mit einer Frequenz von ca. 12MHz. Clock-Initialisierung 
hier

void SpeedUpClock(void)
{
  BCSCTL2 |= DCOR;                          // Rosc
  BCSCTL1 = RSEL0 + RSEL1 + RSEL2;          // XT2on, max RSEL
  DCOCTL = 0xff;
  _BIS_SR(OSCOFF);                          // XTAL not used
}

Mit Hilfe folgender Interrupt-Routine wird der Port 6 eingelesen und der 
Wert in einen Buffer geschrieben.

// Port 2 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
//  P4OUT ^= 0x08;                         // Toggle P4.3
  *(PORTCODES + a) = P6IN;                 // Port 6 einlesen
  P2IFG &= ~0x02;                          // P2.1 IFG cleared
  a++;
}

Mit dieser Methode kann ich die Interrupt-Routine sicher mit einem 
Triggersignal von 4us an Port 2.1 "anspringen"!

Fragen:
1. Hat jemand eine Idee wie ich das noch optimieren kann, um auf ca 2us 
zu kommen?

Mfg

MSP430-FAN

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne die Architektur nicht, aber u.U. geht Polling noch was 
schneller... der Controller kann bei deiner Taktung wahrscheinlich eh 
nichts wirklich Sinnvolles mehr nebenher machen.

Ansonsten auf Assembler umsteigen, da lässt sich mit Sicherheit noch was 
rausholen.

Ansonsten das 'a++' in '*(PORTCODES + a) = P6IN;' reinziehen. Vielleicht 
spart das nochmal einen Cycle beim Optimieren.

Oder 'a' mit 'PORTCODES' statt mit 0 initialisieren, spart u.U. eine 
weitere Addition.

Nur ein par Ideen - ob das was du da tust sinnvoll ist sei mal 
dahingestellt...

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja,

was macht
P2IFG &= ~0x02;                          // P2.1 IFG cleared
aktiviert das die Interrupts wieder? Macht der Controller das nicht 
automatisch beim Verlassen des Handlers?

Lass in diesem Falle die Zeile besser weg. Die paar Zyklen, die der 
Interrupt-Handler früher wieder verfügbar ist, rächen sich mit einem 
Stack-Overflow, wenn der Controller wirklich davon Gebrauch macht!

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
12MHz bei einer CPU die für max 8MHz spezifiziert ist? Mutig.

Naja, in den Interrupt springen benötigt 6 Zyklen (bei 12MHz 500ns), 
Interrupt verlassen benötigt 5 Zyklen (416ns). Sind zusammen 11 Zyklen 
bzw. knapp 1µs.

Sooo...dann hast du für die Abarbeitung deiner Befhle da nur noch 13 
Zyklen Zeit. Allerhöchstens, denn ich weiß nicht, ob der ohne 
Verzögerung nach dem RETI wieder den neuen Interrupt anspringt.
Das wird haarig.

Und ja, das Pin-Interrupt Flag muss man selbst löschen, das ist nur die 
Anzeige, welcher Pin ausgelöst hat, nicht das Interrupt Enable.

Autor: Andreas H. (msp430-fan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Infos!

Hat jemand eine Assembler Referenz mit der Angabe von Clock-Zyklen pro 
Befehl?

Autor: MSP (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TI auf alle Fälle !

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würd mal sagen: Vergiss es per IRQ!
Wie schon gesagt wurde, hast Du 24 Taktzyklen (TZ) zur Verfügung
(2µs bei 12MHz -> 24TZ)
11 TZ verbrät allein die Interruptanforderung + RETI, bleiben Dir also 
effektiv noch 13TZ übrig.
Meine schnellste Assemblerlösung lautet:
; Rx: beliebiges Register, muss einmal mit 0 initialisiert werden
; Rx darf sonst nirgends verändert werden, nur in ISR!
; BUF: Anfangsadresse des Buffers
MOV &P6IN, BUF(Rx)    ; P6IN in Buffer kopieren (6TZ)
ADD #0x01, Rx         ; Index erhöhen (1TZ)
BIC #0x02, &P2IFG     ; IRQ-Flag löschen (4TZ)
Macht zusammen 11TZ

Bleiben Dir also noch ganze 2TZ übrig!

Da aber nach Rücksprung aus der ISR mindestens ein Befehl im "normalen" 
Programm ausgeführt wird, bevor wieder in die ISR gesprungen wird, und 
dieser Befehl durchaus länger als 2TZ dauern kann, ist Dein gefordertes 
Timing meines Erachtens so nicht zu erreichen!
Selbst MSP430F2xxx @ 16MHz scheint mir recht knapp bemessen!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mögliche Ansatz mit Polling (ohne Gewähr)
LOOP:  BIT #0x02, &P2IFG     ; IRQ-Flag pollen (4TZ)
       JEQ LOOP              ; Loop, solagen kein IRQ (2TZ)
       MOV &P6IN, BUF(Rx)    ; P6IN in Buffer kopieren (6TZ)
       ADD #0x01, Rx         ; Index erhöhen (1TZ)
       BIC #0x02, &P2IFG     ; IRQ-Flag löschen (4TZ)
       CMP #N, Rx            ; Abbruch nach N durchläufen (1 oder 2TZ)
       JNE LOOP              ; Loop (2TZ)
       ...                   ; weiter nach Abbruch...

wären dann 20 oder 21TZ (je nach N).
Könnte vielleicht klappen :-)

Autor: Andreas H. (msp430-fan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich kam auch schon auf die Idee die ISR in assembler zu implementieren. 
Mit dem IAR kann ich CPU Register freihalten (z.B R4 und R5). Dieses 
Prozessorregister kann ich dann für den INC im Buffer verwenden.

Wie sollte die ISR in Assembler aussehen?

// Port 2 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
  *( PORTCODES + a ) = P6IN;                 // Port 6 einlesen
  P2IFG &= ~0x02;                          // P2.1 IFG cleared
  a++;
}

Vorallem wie bringe ich es dem IAR als inline assembler bei?

Ciao und Danke

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist überhaupt mit einer Abbruch-Bedingung? Irgendwo muss der 
Interrupt ja mal freigegeben und gesperrt werden? Der Prozessor soll ja 
sicher noch andere Sachen machen und nicht unendlich lange den 
Port-Status in ein Register sortieren. Oder wie dachtest du das? Das 
sind ja auch nochmal Befehle, die abgearbeitet werden müssen.

Und wieso gerade einen MSP430 für sowas schnelles? Den 50% über seiner 
max. Taktfrequenz zu betreiben wird eh nicht sehr zuverlässig 
funktionieren, der Prozessor macht dann manchmal komische Sachen.

Autor: Andreas H. (msp430-fan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zur Info was ich gerade probieren möchte:

1. Ich habe einen PC der mir auf dem LPC-Bus Port 80h ausgaben macht.

2. Am LPC-Bus hängt ein PLD der die Ausgaben decodiert und an einer 
7-Segment-Anzeige die Port 80h codes anzeigt.

3. Mit dem MSP möchte ich die Codes an Port 6 einlesen

4. Über die serielle Schnittstelle des MSPs möchte ich dann die Port 80h 
Codes an einen Host-Rechner senden

Ciao

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie sollte die ISR in Assembler aussehen?
Beratungsresistent ? ;-)
Ich habe doch schon dargelegt, warum eine ISR-Lösung nicht funktionieren 
kann!
Und 'ne Alternative hab ich Dir auch schon vorgeschlagen...

Autor: msp430-fan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Stefan,

ich habe deine Assembler Beispiele gesehen. Ich möchte es auch so 
probieren. Aber wie bringe ich es dem IAR compiler bei? Ich wollte 
"inline assembler" Befehle verwenden. Mein Hauptprogramm sollte schon in 
C codiert sein. Ich will nur die ISR in assembler.

Ciao

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber wie bringe ich es dem IAR compiler bei?
Schon mal den "C/C++ Compiler Reference Guide" konsultiert?
Stichwort "Inline Assembler"

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wäre es denn mit der DMA-Engine des MSP430. Einmal einstellen, und 
dann schießt der DMA die Daten vom Port in den Puffer, kümmert sich ums 
inkrementieren und bei Bedarf kannst du die mit einem weiteren DMA Kanal 
gleich auf dem UART schicken.

Wenn du vorher weißt, wieviele Bytes diese Karte an den MSP sendet, 
kannst du das als transfer size dem DMA Controller gleich geben, der 
Rest läuft in Hardware dann ab.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.