Forum: Digitale Signalverarbeitung / DSP / Machine Learning SAR Werte einlesen TMS320VC5505 EVM


von Martin R. (garnix)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich mache meine Diplomarbeit auf dem TMS320VC5505 Evaluation Board.
Vorher hatte ich noch nicht so viel Kontakt mit Mikrocontrollern/DSPs. 
Nur das was man so in den Vorlesungen hört.
Stehe gerade in den Startlöchern und mache erste Gehversuche...
D.h. "Hello World", serielle Ausgabe und Werte einlesen/ausgeben 
klappt...
Nur leider klappt es nicht Werte äquidistant einzulesen...
Ich verwende die CSL und möchte 1024 Werte pro Sekunde einlesen und über 
RS232 weitergeben (Als Block zum Beispiel jede Sekunde).
Das Werte einlesen dachte ich mir mach ich mit Interrupts.
Habe gesehen es gibt noch andere Möglichkeiten zum Beispiel direkt über 
DMA ins Memory oder Polling.
Meinen Timer 0 habe ich jetzt so konfiguriert:

hwConfig.autoLoad  = GPT_AUTO_ENABLE;
hwConfig.ctrlTim  = GPT_TIMER_ENABLE;
hwConfig.preScaleDiv= GPT_PRE_SC_DIV_6;
hwConfig.prdLow    = (sysClk)/4;
hwConfig.prdHigh  = 0x0000;

wobei sysClk der Takt ist. Das Beispiel ist angelehnt an das CSL 
Beispiel "csl_gpt_example.c"

Mein Interrupt gibt als Test immer die aktuelle Zeit aus:
RTC_getTime(&getTime);
printf("\nTime and Date is : %02d:%02d:%02d:%04d\n",
  getTime.hours,getTime.mins,getTime.secs,getTime.mSecs);

Die Zeitdifferenz zwischen zwei Ausgaben ist jedoch immer 
unterschiedlich...

Jetzt meine Fragen:
1) Was mach ich falsch mit den Interrupts?
2) Wie macht man so etwas eigentlich profimäßig (SAR und DMA, Werte 
schreiben in einen Ringpuffer?)

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Zunächst würde ich für Zeitmessungen niemals Ausgaben über die serielle 
Schnittstelle verwenden (besonders nicht mit so komplizierten Funktionen 
wie printf), sondern immer einen Pin toggeln und am Oszilloskop messen.

Dann weiß ich auch gerade nicht, wie die Uhr (getTime.xx) aus deinem 
Beispiel überhaupt funktioniert, bzw. ob sie richtig geht.

1024 samples pro Sekunde sind nicht sehr schnell. Das lässt sich 
problemlos in Interrupts behandeln. Man baut sich also zwei Interrupts:

1: Timerinterrupt, der mit der gewünschten Samplingfrequenz auslöst und 
die AD-Wandlung startet.

2: ADC-Conversion-Complete Interrupt, in dem das Wandlungsergebnis aus 
dem Wandler ausgelesen wird und irgendwo abgespeichert wird.

Event-gesteuertes AD-Triggern und Kopieren der Daten mit DMA braucht man 
eigentlich erst, wenn es richtig schnell werden muss. Das wird 
beispielsweise bei Audioanwendungen langsam sinnvoll.

Grüße,

Peter

von Detlef _. (detlef_a)


Lesenswert?

Du gibst 15 Zeichen aus, mal 10Bit*1024 ist schon mehr als 115200Baud, 
das kann so nicht gehen.

Cheers
Detlef

von Martin R. (garnix)


Lesenswert?

Ok, danke erstmal. Dass ich eine Funktion (die eventuell wiederum einen 
Interrupt auslöst) im Interrupt ausführe erscheint mir jetzt auch 
hirnrissig.
Ich habe das ganze mit dem Oszi mal überprüft und komme jetzt auch 
zurecht mit der Taktung.

@Detlef: Macht das EVM 5505 maximal ne Baudrate von 115200?

Ich habe jetzt noch ein anderes Problem festgestellt.
Und zwar versuche ich momentan dahinterzukommen wie die sysclock 
festgelegt wird.

Eine Funktion aus der CSL habe ich direkt übernommen.
Diese liefert aber bei 100Mhz einen Takt von 131203khz, bei 75Mhz 
31195khz, bei 40Mhz 5151 usw. Komme jetzt nicht ganz hinter dieses 
System ;-)
Aus den Registern und dem User Guide werde ich auch noch nicht so 
richtig schlau.
1
Uint32 getSysClk(void)
2
{
3
  Bool      pllRDBypass;
4
  Bool      pllOutDiv;
5
  Bool      pllOutDiv2;
6
  Uint32    sysClk;
7
  Uint16    pllVP;
8
  Uint16    pllVS;
9
  Uint16    pllRD;
10
  Uint16    pllVO;
11
  Uint16    pllDivider;
12
  Uint32    pllMultiplier;
13
14
  pllVP = CSL_FEXT(CSL_SYSCTRL_REGS->CGCR1, SYS_CGCR1_MH);
15
  pllVS = CSL_FEXT(CSL_SYSCTRL_REGS->CGICR, SYS_CGICR_ML);
16
17
  pllRD = CSL_FEXT(CSL_SYSCTRL_REGS->CGICR, SYS_CGICR_RDRATIO);
18
  pllVO = CSL_FEXT(CSL_SYSCTRL_REGS->CGOCR, SYS_CGOCR_ODRATIO);
19
20
  pllRDBypass = CSL_FEXT(CSL_SYSCTRL_REGS->CGICR, SYS_CGICR_RDBYPASS);
21
  pllOutDiv   = CSL_FEXT(CSL_SYSCTRL_REGS->CGOCR, SYS_CGOCR_OUTDIVEN);
22
  pllOutDiv2  = CSL_FEXT(CSL_SYSCTRL_REGS->CGOCR, SYS_CGOCR_OUTDIV2BYPASS);
23
24
  pllDivider = ((pllOutDiv2) | (pllOutDiv << 1) | (pllRDBypass << 2));
25
26
  pllMultiplier = ((Uint32)CSL_PLL_CLOCKIN * ((pllVP << 2) + pllVS + 4));
27
28
  switch(pllDivider)
29
  {
30
    case CSL_PLL_DIV_000:
31
    case CSL_PLL_DIV_001:
32
      sysClk = pllMultiplier / (pllRD + 4);
33
    break;
34
35
    case CSL_PLL_DIV_002:
36
      sysClk = pllMultiplier / ((pllRD + 4) * (pllVO + 4) * 2);
37
    break;
38
39
    case CSL_PLL_DIV_003:
40
      sysClk = pllMultiplier / ((pllRD + 4) * 2);
41
    break;
42
43
    case CSL_PLL_DIV_004:
44
    case CSL_PLL_DIV_005:
45
      sysClk = pllMultiplier;
46
    break;
47
48
    case CSL_PLL_DIV_006:
49
      sysClk = pllMultiplier / ((pllVO + 4) * 2);
50
    break;
51
52
    case CSL_PLL_DIV_007:
53
      sysClk = pllMultiplier / 2;
54
    break;
55
  }
56
57
  /* Return the value of system clock in KHz */
58
  return(sysClk/1000);
59
}

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>Diese liefert aber bei 100Mhz einen Takt von 131203khz...

Mit den C5000 kenn ich mich jetzt nicht wirklich gut aus, aber normal 
gibt es diese Funktionen bidirektional.
Also eine, die die Pll auf eine gewünschte Ausgangsfrequenz konfiguriert 
(natürlich nur, wenn das richtige Quarz angeschlossen ist).
Und eine andere, die man aufrufen kann, um die aktuell konfigurierte 
Frequenz auszulesen.

Wenn darin kein Fehler ist, sollte sich genau die eingestellte Frequenz 
auch wieder auslesen lassen.

Grüße,

Peter

von Guliver L. (smithjnr)


Lesenswert?

Hallo garnix,

da hat der Prof ja eine schöne Aufgabe gestellt :-)
Ich arbeite mit dem 6713 und dem AIC23, also etwas anders als bei diesem 
Board. Hier meine Anmerkungen.

Ich habe mir das Board und den DSP mal kurz angesehen.

Da der 5505 ein Festkomma-DSP ist, muss bei den Algorithmen die 
Wortbreite des DSPs unbedingt berücksichtigt werden. Simulationen 
(Matlab) und die erste Implementierung von Algorithmen werden oft in mit 
Fließkommaoperationen durchgeführt.
Die Umsetzung von Fließ- in Festkommaoperationen ist nicht trivial, 
anders als es vielleicht im ersten Moment aussieht. Das stellt einen 
erhöhten Schwierigkeitsgrad dar. Weiß das der Prof?

Ich habe das früher so gemacht, dass für die Simulation in Matlab meine 
Algorithmen in C mit einstellbarer Wortbreite implementiert habe und 
somit die Dynamik der Algorithmen überprüft habe.
Ach so, simulieren muss man eigentlich immer, wenn man mit dem DSP 
arbeitet.

Unglücklich ist auch, dass sich die SPI-Schnittstelle zum AIC nur im 
Master-Mode betreiben lässt. So muss wahrscheinlich wirklich, wie oben 
schon erwähnt, mit dem Timer_IRQ zum Abholen der Samples gearbeitet 
werden.
Eleganter geht's beim 6713: Der AIC ist im Master-Mode, liefert die 
Samples über die serielle Schnittstelle (McBSP), die Schnittstelle 
generiert einen IRQ zum EDMA-Controller, der sammelt die vorgegebene 
Anzahl von Samples ein (z.B.1024) und liefert dann, wenn alles 
vollständig ist, einen IRQ zum DSP. Der DSP ist die ganze Zeit nicht in 
den Transfer involviert.

TI liefert seine Beispiele oft mit Pollin-Mode aus. Das ist sehr 
unelegant. Trotzdem würde ich mich zunächst an die Beispiel von TI 
halten.

Werden bei Beispielen für dieses Board schon IRQs von TI verwendet?
Läuft die FFT schon?

Grüße,
smithjnr

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.