www.mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP zu langsame Programmausführung bei TMS320F2812 DSP


Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Folgende Hardware aus einem Uniprojekt:
- TMS320F2812
- 50 Mhz Clock (DS1077L)
- externes Ram von cypress

Der DSP ist auf 50 Mhz geflasht, Clockprescale auf 2
(Sysclock=2/2*50=50mhz).
Im Code werden auch Berechnungen für die Baudrate durchgeführt die von
50 Mhz ausgehen - Uart funktioniert.
Auch ein 5ms Timer der per CCS ConfigureCPUTimers(....) auf 5ms
initialisiert wird funktioniert korrekt.

Wir laden das Programm nach dem erzeugen mit dem Debug-JTag auf den DSP
(es wird nicht geflasht, nur ins ram).

Nun das problem:
/* sehr viele initialisierungen, komplexes, wirres projekt */
/* ...                                                     */
while(1){
 KickDog(); //reset wdt
 GpioDataRegs.GPBDAT.all = 0xFFFF;
 GpioDataRegs.GPBDAT.all = 0x0000;
}

Ich lasse nun diesen Code laufen und messe mit Oszi an Pin B3.
Wenn ich aus der Länge der Low-Periode auf die Taktrate zurückrechne
komme ich darauf dass der DSP nur mit 0,5 Mhz läuft !

Der selbe Code auf dem Prototypboard (ezDSP Board, 30Mhz) läuft auch
dort
zu langsam mit 0,3Mhz.

Auch hier wieder der Faktor 100.

Wenn wir ne kleine for-schleife einbauen die nen int bis 500 zählt
während der pin high ist messen wir einige ms (!!) Ausführungszeit.

Wenn ich den ganzen Overhead aus dem Projekt rauswerfe
und nur ein Beispiel von TI (toggle) laufen lasse
bekomme ich die volle Taktrate am IO Pin.

Wir haben jetzt versuchsweise soviele Initialisierungen wie möglich
aus dem Projekt entfernt (alle (?) Interrupts aus etc).
Trotzdem noch das verhalten.

Hat jemand eine Idee was diesen 100er prescaler verursachen könnte ?
Das Projekt ist schon sher groß und wirr programmiert, können wir
nichts für,
war schon vor uns so ;)

Evtl irgendein Register das man setzen kann das sowas verursacht ?
Programmiert wird mit dem Code Composer Studio von TI.

(Da funktioniert das debuggen aber nicht richtig, das ganze Studio ist
ne Zumutung :-X)

Danke schonmal ;)

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schonmal in das Assembler-Listing gesehen? Kann man im CCS nicht im
Schrittbetrieb sehen, was mit jedem Takt abgearbeitet wird?

Ich kann zwar nur für AD sprechen, aber auch dort ist C-Code in meinen
Augen eine Katastrophe, weshalb ich in Assembler programmiere.

Geh einfach davon aus, dass dir der Compiler unter Umständen einen
ordentlichen Overhead erzeugt.


Alex

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ist leider nicht ganz so einfach. Dieses Studio sollte prinzipiell
step by step durch den code debuggen können.
Geht leider nur bei einigen C Sourcen. Die anderen kann er nicht
anspringen.
(breakpoints angeblich auf ner ungültigen linie, step into meldet auch
irgendeinen fehler)

Wenn ich mir die for schleife per Hand suche sehe ich das sie ca. 10
Zeilen asm braucht pro loop.
Das erklärt aber auch den Faktor 100 nicht.
Zumal es ja in dem kleinen Testprogramm das nur aus dem nötigsten
besteht nicht auftritt.

Wenn nur der Debugger richtig arbeiten würde :(

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal versuchen die Optimierung auszustellen. Vielleicht hilfts ja.

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die sollte eigentlich aus sein. Kann ich aber erst nächste Woche wieder
gucken.

Autor: Carsten St. (carsten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du mal gemessen, wenn der das Board Stand-Alone läuft und nicht am
Debugger hängt?

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne...
Aber ich starte das Programm ja ganz normal (run).

Ausserdem läuft ja ein anderer Testcode (nur Portdir setzen und 10 in
ner while schleife ausgeben)
unter denselben Bedingungen mit voller Geschwindigkeit.

Wenn ich unser großes Projekt nehme und dort die main schleife durch
dieselbe while(1) schleife ersetze läuft es so lahm...

Da ist bestimmt irgendein Register falsch gesetzt oder ein Interrupt
spukt die ganze zeit rum und verschwendet 90% der Rechenpower.

Dachte evtl hatte schonmal jemand das selbe Problem und könnte sagen
guck mal ob
Register xy gesetzt wird.

Gibt es einen befehl um testweise alle Interrupts auszuschalten ?
Also sowas wie cli() bei den Atmels..

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hast du das RAM Interface initialisiert ? Wieviel Wait-States etc.
?

Gruß Thomas

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Wird das in der cmd Datei initialisiert ?

Die sieht so aus:
/****************************************************************************/
/*   rob.cmd
/****************************************************************************/

MEMORY
{
   PAGE 0 : BOOT(R)     : origin = 0x3f8000, length = 0x80
   PAGE 0 : PROG(R)     : origin = 0x3f8080, length = 0x1f80
   PAGE 0 : RESET(R)    : origin = 0x000000, length = 0x2
   PAGE 1 : XINTF6    : origin = 0x100000, length = 0x80000 /* external
RAM */
   PAGE 1 : XINTF7    : origin = 0x3fC000, length = 0x4000  /* external
RAM */

   PAGE 1 : M0RAM(RW)   : origin = 0x000000, length = 0x400
   PAGE 1 : M1RAM(RW)   : origin = 0x000400, length = 0x400
   PAGE 1 : L0L1RAM(RW) : origin = 0x008000, length = 0x2000
   PAGE 1 : ZONE2       : origin = 0x080000, length = 0x080000     /*
XINTF zone 2 */

   
}
 
SECTIONS
{
   /* 22-bit program sections */
   .reset   : > RESET, PAGE = 0, TYPE = DSECT
   .pinit   : > PROG,  PAGE = 0
   .cinit   : > PROG,  PAGE = 0
   .text    : > XINTF6,  PAGE = 1
   

   /* 16-Bit data sections */
   .const   : > M0RAM, PAGE = 1
   .bss     : > M1RAM, PAGE = 1
   .stack   : > M1RAM, PAGE = 1
   .sysmem  : > L0L1RAM, PAGE = 1

   /* 32-bit data sections */
   .ebss    : > L0L1RAM, PAGE = 1
   .econst  : > L0L1RAM, PAGE = 1
   .esysmem : > L0L1RAM, PAGE = 1
   .cio   : > L0L1RAM, PAGE = 1
   
   /* external ram */
   .frame  : > ZONE2, PAGE = 1


   .boot > BOOT
   {
      -lrts2800_ml.lib<boot.obj> (.text)
   }
}

Waitstates werden scheinbar nirgendwo definiert.

Gibt es zum Thema F2812 und ext Ram irgendwelche guten Manuals ?
Ich habe bis jetzt nichts wirklich brauchbares gefunden ...

Aber in unserem mini Testprogramm funktioniert das pintoggeln immer
richtig.
Egal ob  .text und .ebss im externen oder internen bereich liegen.
Dort werden auch keine Waitstates gesetzt.

Autor: Carsten St. (carsten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest dir wirklich den erzeugten Assemblercode mal anschauen.
Glaube nicht das dein Zugriff zu lngsam ist, sonder einfach zuviele
erzeugt werden.
Was lernen wir daraus? Wenn die Zeit stimmen muss, nimm Assembler. (hat
glaub ich mein Prof mal gesagt)

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Den Asm code hatte ich mal angesehen. Der sieht ok aus.
Auch wenn ich 10 Takte für ne Schleife bissl viel finde.

Ein simples
Portb = 0xffff;
Portb = 0x0000;
Portb = 0xffff;
Portb = 0x0000;
Portb = 0xffff;
Portb = 0x0000;
Portb = 0xffff;
Portb = 0x0000;
...
braucht auch pro Zeile 100x so lange als normal.

Extra schnell muss es nicht sein...
Aber wir würden schon gerne mehr als 0,5Mhz von dem DSP ausnutzen ;)

Wenn eine
portb=0xFFFF;
portb=0x0000;
for (i=0; i<500; i++){
 x=x*1;
}
portb=0xFFFF;
Schleife 10 ms (!) braucht kann man den DSP so nicht wirklich nutzen
.
Das waren in asm ca 10 assembler befehle.
Sprich grob gerechnet ca 10 * 500 = 5000 Takte
-> 50Mhz -> 50.000.000 Takte pro s
-> 50.000.000/5000 = 0,0001 s = 0,1ms
Bei uns läuft also alles um den Faktor 100 zu langsam.

Damit dauert eine Reglerschleife eines einfachen PID Reglers >6ms...
Da muss irgendwas spuken, simpler asm Overhead kann das nicht sein.

Da ist ja jeder 8Mhz Atmel schneller :(

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der 2812 ist schon sehr flott und die angegebene Routine sollte im
internen RAM ohne waitstates mit voller Geschwindigkeit laufen. ALso in
deinem Fall mit 20ns. Ich hab das ganze auch mit vollen 150MHz laufen
und das geht wie erwartet. Zum externen Memoryinterface schau in die
entsprechenden Datenblätter von TI. Dann hast du das Wochenende zu tun
zum lesen :o)))....

Die ensprechende Info steht in SPRU067C oder bei TI die ganzen
Handbücher auf der TMS320F2812 Seite anschauen. Das sind schon einige
MB an Datenblättern.

Das XINTF wird nicht im *.cmd file initialisiert. Dort wird nur dem
Linker mitgeteilt, wo die einzelnen Speicherbereiche liegen.

Das muss in deinem Programm passieren.

die besten Grüße und viel Erfolg
Thomas

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Wir haben das Problem gefunden ! Vielmehr waren es zwei Probleme...

1.)
Irgendeine Initialisierung sorgt für eine Verlangsamung um den Faktor
10.
Ich vermute irgendeine Initialisierung eines reserved registers.
Also bit2-15 reserved, bit0-1 soll auf 00 gesetzt werden:
register = 0x0000;
Solche Stellen haben wir einige im Code gefunden... argh...
Wo das passiert haben wir noch nicht rausbekommen. Wenn wir
die ganze anwendungsspezifische Initialisierung weglassen läuft der DSP
schneller.

So, und nun der Hauptfaktor:
2.)
Unser Programm ist zu groß für den internen Ram -> es läuft aus dem
externen Ram.
Das Speicherinterface wurde aber nirgends (!) initialisiert.
Danke für den Tipp Thomas!
Wir haben jetzt mal das run_from_xintf example modifiziert und damit
läuft es nun.
Auch dies brachte einen Faktor x10.

-> wenn beide Fehler behoben sind läuft der DSP mit seiner vollen
Geschwindigkeit :D

Danke euch allen für die Tipps ;)
Wenn wir rausgefunden haben welche Registerzuweisung den ersten /10
Faktor verursacht
werde ich das hier posten ;)

Autor: TLA (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, habe ein ähnliches Problem. Wo kann ich das das run_from_xintf
example finden?

Autor: Sssssss (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich meine es müsste hier drin sein:
http://focus.ti.com/docs/toolsw/folders/print/sprc097.html

Hab jetzt nicht reingeguckt, bei uns war es auf einer Schulungscd ;)

Gruss,
Simon

Autor: udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI leute,

ich habe auch einen 2812er. Ich habe vor eniger Zeit auch einige
Performance-Tests mit Code im internen,externen und Flash Speicher
durchgeführt. Ergebnis : ohne Initialisierung läuft der interne RAM
ohne Waitstates der Flash mit 16 waitstates und der externe RAM mit 50
oder 100(weiss ich nicht mehr ganz genau, jedenfalls sehr viele).

Da ich mir zur Zeit Code von Simulink erzeugen lasse, der den Code zum
größten Teil in den externen RAM(also via XINTF) legt, wird das Thema
für mich wieder aktuell.

Ich habe mich nie besonders ausgiebig mit den
Timing-Diagrammen/Abläufen bei Speicherzugriffen beschäftigt. Deshalb
eine Frage. Wie optimiert man den das Timing? Was ist zu beachten?

Man könnte sonst auf die Idee kommen die Waitstates(PAGE?/RANDOM?)
einfach so lange zu verringern, bis das DSP-Programm nicht mehr
vernünftig läuft. Das ist aber keine Garantie, dass bei dem gefundenen
minimalen Wert der DSP in allen Situationen korrekt operiert, denke ich
mal so.

Wäre dankbar für eine Antwort, die zeigt wie man eine solche Berechnung
sinnvoll durchführt.

Euer udo

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.