Forum: Digitale Signalverarbeitung / DSP / Machine Learning TMS320F28016 ist zu langsam


von Marc B. (marcberg)


Lesenswert?

Hi, ich habe folgendes Problem:
Die Ausfürungszeit eines Befehl (Assemblerbefehls) benötigt anscheinend 
7 Taktzyklen.

Umgebung:
Testboard von Olimex für TMS320F28016
60 MHz Systemtakt
Entwiscklungsugebung CCS4.0

Ich habe folgendes Testprogramm:

startLabel:
   GpioDataRegs.GPASET.bit.GPIO0 = 1;
   GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
   goto startLabel;

Mit dem Oszi benötigt das Signal zwischen den beiden Kommandos ca. 117 
ns, also ca. 7 Taktzyklen.

Das Programm habe ich im Flash, für den ich bereits mit InitFlash() 
bereits das Pipelining und die WaitStates angepasst habe (hoffentlich 
richtig).

Ich habe das Programm bereits ohne JTAG-Emulator direkt vom FLASH 
gestartet -> gleiches Verhalten

Ich hoffe auf gute Ratschläge.

von doofi (Gast)


Lesenswert?

Marc Bergdolt schrieb:
> startLabel:
>    GpioDataRegs.GPASET.bit.GPIO0 = 1;
>    GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
>    goto startLabel;

Der Compiler (ich benutze noch CCS33) erzeugt ziemlich
üblen Assemblercode für solch Bitgefrickel.

Schau Dir mal den Assemblercode an, da dürfte das Verbesserungspotential
leicht zu finden sein.

von (prx) A. K. (prx)


Lesenswert?

Ist dass eine Art High-Level-Assembler oder C? Wenn es C ist, dann fehlt 
zur Bewertung der Ursache Laufzeit der Assembler-Code.

von Marc B. (marcberg)


Lesenswert?

stimmt.

Ist das so richtig, dass jedes Kommando diese 7 Taktzyklen benötigt?
In der Dokumentation von TI steht bei den Assemberlbefehlen jeweil die 
Cycle-Anzahl.
Die diesem Testprogramm müssten das (OR-Befehl) 1 Zyklus sein, also eine 
Ausführungszeit von 16.67 ns.
Bei mir sind es aber 7 Zyklen.

Was könnte ich falsch gemacht haben?

von (prx) A. K. (prx)


Lesenswert?

Sorry, hatte den Post ("wo ist die Frage?") gelöscht, weil ich die Frage 
mittlerweile erraten hatte.

Nun kenne ich die TMS320er nicht und DSPs habe teilweise sehr spezielle 
Befehlssätze, insofern ist der Assembler-Code schwer zu erraten.

Viele Prozessoren benötigen mehrere Takte für scheinbare einfache C 
Statements, sei es weil komplexe Befehle länger dauern, sei es weil 
mehrere Befehle erzeugt werden.

Bei ARMs beispielsweise wird aus
  IOport = 1;
eine Sequenz von 3 Befehlen, darunter ein langsamer Ladebefehl aus dem 
Flash. 7 Takte wären dafür völlig normal.

> Was könnte ich falsch gemacht haben?

Es auf Hochsprachen-Ebene zu analysieren.

von Tim R. (Gast)


Lesenswert?

Also wenn der Code aus dem Flash ausgeführt wird, dann sind eindeutig 
Waitstates im Spiel. Aus dem SRAM sollte es schneller gehen.
Wenn der TMS320F28016 zu langsam ist, dann sollte man es ansonsten mal 
mit dem TMS320F2801(100Mhz) versuchen.

von Marc B. (marcberg)


Lesenswert?

Zur Ausführung aus dem internen RAM noch eine Bemerkung.
Ich habe es gerade nochmals probiert.

Bei der Ausführung vom RAM dauert es genauso lange, also ebenfalls
7 Taktzyklen.

die 60MHz würden für meine App schon ausreichen.

von doofi (Gast)


Lesenswert?

A. K. schrieb:
> Ist dass eine Art High-Level-Assembler oder C? Wenn es C ist, dann fehlt
> zur Bewertung der Ursache Laufzeit der Assembler-Code.

Dem ist nichts hinzuzufügen  :-)

von Marc B. (marcberg)


Lesenswert?

Anbei noch der komplette Assembler-Code aus dem Disassembler:

C$L1:
GpioDataRegs.GPASET.bit.GPIO0 = 1;
MOVW       DP,#0x01BF
OR         @2,#0x0001

GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
OR         @4,#0x0001

goto startLabel;
SB         C$L1,UNC

von Jens (Gast)


Lesenswert?

Servus
Ich benutze auf der Arbeit den TMS320F28335. Wir haben so etwas 
Ähnliches auch versucht. Das liegt nicht an dem Assembler, sondern du 
kannst den Ausgangsport nicht mit 60MHz umladen. Die Treiber sind 
einfach nicht schnell genug. Die Pins haben ja eine kleine Kapazität und 
dann sind an den Ausgängen noch Schutzdioden. Also nochmal Kapazität. Da 
müsste der TMS einen riesigen Strom zum umladen treiben können. Das kann 
er aber nicht. Aber intern kann er mit dem Takt rechnen.

Gruß, Jens

von Marc B. (marcberg)


Lesenswert?

Hi Jens,

stimmt.
Ich habe zwischen den beiden Kommandos zum Ausgang setzen/rücksetzen 
drei andere Kommandos gesetzt.
Ich bekomme dann die selbe Zeit am Oszi angezeigt.

Vielen Dank!
Vielen Dank auch an alle anderen!

von (prx) A. K. (prx)


Lesenswert?

Ich denke nicht, dass die Pinkapazitäten eine Rolle spielen. Wohl aber 
die Busstrukturen. Auch hier will ich mangels Kenntnis der TMS320 ein 
Beispiel aus dem ARMs bringen:

Dort finden sich immer mehrere interne Busse. Sehr schnelle innerhalb 
des Cores und zwischen Core und Caches/Speichern, mässig schnelle 
zwischen Core/Cache und performanten Funktionsblöcken (AHB) und eher 
gemächlich arbeitende Busse zu den weniger performanten 
Periphierieeinheiten (APB).

Solche langsameren Peripheriebusse sind oft nicht in der Lage, mit dem 
Tempo des Prozessors mitzuhalten. So kann ein solcher Bus u.U. nur alle 
paar Takte eine neue Operation ausführen. Je nach Befehl, Konfiguration 
und Bauart kann dies einen Prozessorbefehl direkt abbremsen (bei 
Leseoperation unvermeidlich), oder die Busoperation wird angestossen und 
arbeitet dann autark weiter (bei Schreiboperation möglich), wobei dann 
der nächste Befehl evtl. verzögert wird, wenn er den Bus anspricht und 
zu früh kommt. Es kann deshalb auch vorkommen, dass ein paar NOPs 
zwischen solchen Befehlen den Ablauf nicht verzögern.

Darüber ist beispielsweise NXP gestolpert. Die ersten LPC2000 hatten 
grottenlangsamen Portzugriff. In nachfolgenden Versionen wurden deshalb 
die Ports vom langsamen APB an den schnellen AHB verlegt. Mit der Folge, 
dass diese neueren Modelle in dieser Frage sehr schnell sind, schneller 
als eine Konkurrenz, deren Ports weiterhin am APB hängen.

von Tim R. (Gast)


Lesenswert?

@Marc Bergdolt

Für welchen Zweck möchtest du die GPIOs nutzen?

von Marc B. (marcberg)


Lesenswert?

@ Tim

Ich möchte mit den ePWMs eine Takterzeugung für Schrittmotoren erzeugen.
(4 Achsen, interpolierte Fahrt in 2D, 3D, 4D und 
Geschwindigkeitsoverride)

Das mit den GPIOs war nur zwischendrin mal ein Test, ob die CPU richtig 
läuft, weil ich den Eindruck hatte, dass mein bisher geschriebener Code 
doch etwas langsam ist.

Ich habe mir nun aber den Assemblercode angeschaut und unter 
Berücksichtigung der Tatsache, dass Sprungbefehle etc. mehrere 
Taktzyklen benötigen, kommt das wohl schon hin.

Ich hatte die letzten Jahre unter Windows Software geschrieben und mache 
jetzt seit längerer Zeit mal wieder was hardwarenahes.
Daran muss man sich erst wieder gewöhnen.

von Tim R. (Gast)


Lesenswert?

Ah interessant. Ich persönlich würde größere DSPs von Ti empfehlen. Z.B. 
den 2808 oder 2809. Für die Entwicklung sind sie eleganter, da sie nicht 
so schnell an Ihren Speichergrenzen kommen. Zunächst habe ich auf einem 
2808 entwickelt und erst später den Code optimiert und reduziert für den 
2801(100Mhz). Allgemein ist die C2000 Serie recht elegant und nach einer 
gewissen Erfahrung leicht zu händeln. Meist kann man den Code 1:1, bzw. 
mit geringen Anpassung, von einem 2801 zu einem TMS320F28335 bringen. 
Die Serie 2801 bis 2809 ist Pin-Kompatibel, dem 28016 fehlt ein SPI 
Kanal. Aber ich schweife etwas ab...
Außerdem ist zukünftig die Piccolo Serie recht interessant, da dieser 
DSP/DSC mit einer Versorgungsspannung auskommt. Sprich es gibt keinen 
Aufwand mehr mit der Initialisierung der Versorgungsspannung -> ca. 3€ 
kann man dadurch sparen. Der interne Oszillator ist aber nicht das Gelbe 
von Ei, aber was will man schon verlangen ;)

Zu den GPIOs: Anscheinend hast du dich schon mit der Dokumentation 
beschäftigt, da du die Register-Anweisung Set und Clear benutzt. Den 
typischen Fehler hast du also umgangen. Für die Mitleser hier: Das DAT 
Register ist nicht zum setzen der GPIOs gedacht.

Allgemein wird der Code recht gut optimiert. Allerdings wird richtig 
großer Assembler-Code erzeugt, wenn:

+ Große Switch-Case Anweisungen genutzt werden
+ For Schleifen (Also wie immer)
+ Besonders For Schleifen, die 32Bit Variablen bearbeiten / berechnen
+ Jeglicher Zugriff auf dem Flash oder bei größeren DSPs Adress- und 
Datenbus.
+ IF Bedingung mit zu vielen Vergleichen - besonders bei 32Bit Variablen

von mischu (Gast)


Lesenswert?

Äh, mal eine Frage:
7 Takte ist für eine komplette Periode oder jeweils zwischen zwei 
Flanken??
Das kann eigentlich nicht sein, da eine Jump im Programmcode dazu füren 
müsste, dass die Zeiten für high und low Pegel unterschiedlich sind.

Hast Du gelesen, dass die maximale Togglefrequenz für GPIOs 25MHz 
beträgt? Ich verstehe dass so, dass man nur ein 12,5MHz Rechtecksignal 
erzeugen kann.

von Marc B. (marcberg)


Lesenswert?

Hi mischu,

Die Zeit (7 Takte) hatte ich zwischen zwei Flanken gemessen.
Ich vermute, dass das mit dem internen Bus zwischen CPU und GPIOs 
zusammenhängt.
Wenn ich zwischen die beiden Kommandos andere Befehle schreibe (ich 
glaube, bis zu 4 oder 5), dann wird die Zeit zwischen den Flanken nicht 
länger.
Ich habe inzwischen auch schon in der Dokumentation eines anderen 
Prozessors gelesen, dass bei der Adressierung der Periphiereinheiten 
Wartezyklen eingelegt werden.
Bezüglich dem TMS320 habe ich das jetzt nicht mehr genau verfolgt.

Ich habe inzwischen herausgefunden, dass für die Division bei den TMS320 
keine Hardwareeinheit zur Verügung steht. Das kommt mir sehr 
ungelegen...
Daher bin ich inzwischen auf der Suche nach einer anderen CPU. (Favorit 
momentan: PIC32)

Das mit den 25 MHz hatte ich nicht gelesen.

von Michael O. (mischu)


Lesenswert?

Ich bin vielleicht nicht mehr auf dem neuesten Stand.
Welcher Prozessor hat denn in der Klasse eine Divisions-Einheit?
Selbst die Sharc DSPs von AD hatten nur eine einfache fixpoint - 
divisionseinheit (Stand vor 3 Jahren).

Wofür benötigst Du die Division überhaupt?

von Marc B. (marcberg)


Lesenswert?

Ja stimmt.
Eine vorhandene Divisionseinheit bedeutet noch nicht eine Division in 
einem Takt. Das hatte ich fälschlicherweise angenommen.
Vorteil der Divisionseinheit ist allerdings, dass sie zur Laufzeit die 
Anzahl der Durchläufe reduziert (Je nachdem, welches das höchste 
gesetzte Bit ist.)

Ich benötige die Division für die Berechnung der folgenden 
Schrittgeschwindigkeiten.
Bei einer Beschleunigungsrampe muss ich von Schritt zu Schritt diese 
Rechnung wiederholen.
Deine Frage 'Wofür benötigst Du die Division überhaupt?' macht mich 
inzwischen etwas stutzig, ob ich mich mit der uC-Arithmetik und 
alternativen Rechenmöglichkeiten noch auseinandersetzen muss.
Ich hatte mich bisher nur auf Vorberechnungen konzentriert. Aber die 
bringen eigentlich nur sehr geringe Einspareffekte.

von Michael O. (mischu)


Lesenswert?

Deine bruchstückhafte Erklärung bringt nicht wirklich Licht in dein 
Projekt.
Ohne etwas genauere Erklärung, was genau du machen möchtest und welche 
Umsetzung dir derzeit vorschwebt, ist keine weitere Hilfe möglich.

Zum Thema Division:
Die ist immer blöd auf einem DSP. Da gibt es nur eine goldene Regel:
Vermeide sie!!

- Alles was zur Compilezeit an Divisionen berechnet werden kann als 
Konstanten definieren.
- Alle abhängigen Parameter zur Laufzeit, die nur selten geändert werden 
am Besten nur bei Initialisierung / Änderung berechnen und in 
zusätzlichen Variablen speichern.
- Alle zur Laufzeit regelmäßig veränderten Werte so umformen, das man 
jeden Divisor nur einmal ausrechnet und dann mit allen anderen Werten 
per Multiplikation an den gewünschten Stellen verwenden.

Tipp:
- Wenn Du langsam veränderliche Werte misst aus denen Du den Kehrwert 
bilden musst, wäre es übertrieben diese mit einer hohen Abtastrate 
aufzunehemn und die Division zu bilden. D.h. du kannst Eigenheiten 
deines Systems ausnutzen, um die tatsächlich notwendige Anzahl 
Divisionen zu realisieren.
- Je nach Auflösung kann auch eine Lookup-tabelle helfen (< 10Bit)
- Analog Devices z.B. verwendet für ihre Float Division eine Funktion, 
die nur einen 8Bit Kerhwert erzeugt. Anschließend wird das Ergebnis per 
Polynom bis auf ein LSB interpoliert.
- Man kann gezielt unterabtasten / Werte länger verwenden und diese 
zwischen mehreren Berechnungen extra / interpolieren.

Du siehst, der Möglichkeiten sind keine Grenzen gesetzt. Welche Lösung 
in Deinem Fall klappt... ist ohne weiteren Input nicht feststellbar.

Gruß
Michael

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.