Forum: Digitale Signalverarbeitung / DSP / Machine Learning Problem mit Blackfin SPI-DMA


von Benjamin S. (recycler)


Angehängte Dateien:

Lesenswert?

Hallo Gemeinde,
ich verwende beim Datentransfer mit einem BF535 das SPI-Protokoll. Damit 
beschreibe ich einen MAX3421E USB-Controller, was auch alles 
funktioniert.
Jetzt will ich auf den DMA-Modus wechseln.
Bei MAX3421 muss als erstes ein Byte gesendet werden, welches das 
Register des Controller beinhaltet und gleich anschließend die Daten für 
das Register. Dabei darf das Chipselect nicht auf high gehen. Wenn der 
Transfer abgeschlossen ist [1 Byte (Register) + 1-64Byte (Daten)] soll 
#CS wieder auf high gehen. Deshalb habe ich mich für eine SoftwareCS 
Leitung entschieden, welche nach Abschluss des Transfers in einer ISR 
gesetzt wird. Allerdings passiert das schon viel zu früh, wie auf dem 
Ausdruck im Anhang zu sehen (rote Linie ist die Solllinie)
Oberes Signal: Chipselect
Unteres Signal: SCK

Für Anregungen bin ich gerne offen.

von Benjamin S. (recycler)


Angehängte Dateien:

Lesenswert?

Hier der Quellcode

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Mein erster Verdacht war, dass dein Interrupt auf DMA completion kommt. 
Und in der Tat, alle Indizien sprechen dafür:

1
Page 10-6 im HRM [1]:
2
3
Interrupt Behavior
4
------------------
5
6
The behavior of the SPI interrupt signal depends on the transfer initiation
7
mode bit field (TIMOD) in the SPI Control register. In DMA mode, the
8
interrupt can be generated upon completion of a DMA multiword transfer
9
or upon an SPI error condition (MODF, TXE when TRAN = 0, or RBSY when
10
TRAN = 1). When not using DMA mode, an interrupt is generated when
11
the SPI is ready to accept new data for a transfer. The TXE and RBSY error
12
conditions do not generate interrupts in these modes. An interrupt is also
13
generated in a master when the mode fault error occurs.
14
15
For more information about this interrupt output, see the discussion of
16
the TIMOD bits in “SPIx Control Register (SPIx_CTL)” on page 10-9.

Also wie sich das ließt, bekommst du einen Interrupt nur auf Error oder 
DMA completion...

[1] 
http://www.analog.com/static/imported-files/processor_manuals/365066229ADSP_BF535_HRM.pdf

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Oha, wie es aussieht, hat das SPI des 535er garkeinen DMA FIFO Buffer! 
(Ich kenne das anders vom 537er.) Das sollte in der Tat bedeuten, dass 
der DMA completion Interrupt erst dann kommt, wenn das letzte Byte raus 
ist. Du prüfst in der Interruptroutine nicht, um welchen Interrupttyp es 
sich handelt. Versuch' das hier:

1
EX_INTERRUPT_HANDLER(SPI0_DMA_ISR)
2
{
3
  // pSPI0_DMA_INT:
4
  // 0x0001 => Interrupt on Completion
5
  // 0x0002 => DMA Interrupt on Error
6
  // 0x0004 => Bus Error
7
8
  if(*pSPI0_DMA_INT & 0x0001) // Interrupt on Completion
9
  {
10
    // CS high
11
    *fio_set_reg   = (unsigned short)0x0400;
12
    // Ack
13
    *pSPI0_DMA_INT = 0x0001;
14
  }
15
  else
16
  {
17
    // Fehlerbehandlung
18
  }
19
}

von Olaf (Gast)


Lesenswert?

Mal abgesehen von den anderen PRoblem, glaubst du nicht das deine
Daten etwas viel Dreck auf deiner CS Leitung hinterlassen?

Olaf

von Benjamin S. (recycler)


Angehängte Dateien:

Lesenswert?

@Olaf: ich denke, das kommt von den langen Messleitungen. Ich hatte 
nichts anderes zur Hand.

@pumpkin: Danke für die Hilfe, die Überprüfung führe ich durch. Den else 
Teil habe ich abgeschnitten.
Das komische ist, wenn ich in der ISR einen Breakpoint bevor das #CS auf 
high gesetzt wird, das die Daten übertragen werden. Dies sehe ich, weil 
ich mit dem Code einen Binärzähler realisiert habe. Wenn ich keinen 
Breakpointsetzte bzw. nach dem CS-high, dann funktioniert das ganze 
nicht mehr und die Daten werden nicht übertragen.
Laut Anhang hat er die Daten (Word Count = 0) abgearbeitet und keine 
Fehler (Config und Status) gefunden. Das ist was mich stutzig macht.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Benjamin Schrödl wrote:
> @pumpkin: Danke für die Hilfe, die Überprüfung führe ich durch. Den else
> Teil habe ich abgeschnitten.

So wie ich vorgeschlagen habe?

> Das komische ist, wenn ich in der ISR einen Breakpoint bevor das #CS auf
> high gesetzt wird, das die Daten übertragen werden. Dies sehe ich, weil
> ich mit dem Code einen Binärzähler realisiert habe. Wenn ich keinen
> Breakpointsetzte bzw. nach dem CS-high, dann funktioniert das ganze
> nicht mehr und die Daten werden nicht übertragen.

Das ist allerdings merkwürdig. Steht das Hochsetzen in der if-Abfrage 
nach dem Acknowledge? Wenn nicht: Versuch macht schlau.

> Laut Anhang hat er die Daten (Word Count = 0) abgearbeitet und keine
> Fehler (Config und Status) gefunden. Das ist was mich stutzig macht.

Ist der "TX Buffer" oben im Bild der vom SPI0? Sollte der leer sein wenn 
die Übertragung abgeschlossen ist (finde auf Schlag nichts im HRM)?

von Benjamin S. (recycler)


Lesenswert?

ich hab das CS-high schon wo anders hingesetzt, aber das bring nix.
der TX buffer beinhaltet den letzten Wert als 2xByte die identisch 
buffer[i] sind

Hier meine ISR:
EX_INTERRUPT_HANDLER(SPI0_DMA_ISR)
 {
  // pSPI0_DMA_INT:
  // 0x0001 => Interrupt on Completion
  // 0x0002 => DMA Interrupt on Error
  // 0x0004 => Bus Error


//Wenn hier breakpoint, dann funktioniert die Übertragung
  *pSPI0_FLG = FLS5 | FLG5;


  if(*pSPI0_DMA_INT & 0x0001) // Interrupt on Completion
   {


    // Puffer fertig abgearbeitet
    if(1 != 0) //*pbuffer = buffer8k)
     {

      buffer8k[1]++;
      c = buffer8k[1];
     }
    else
     {
      // Disable PF_INT

     }

    *pSPI0_DMA_INT         = 0x0001;
   }
  else
   {
    unsigned short e;
    e = 1; // hier 2. Breakpoint, der nie angesprungen wird.
   }
 }

von T. H. (pumpkin) Benutzerseite


Lesenswert?

Benjamin Schrödl wrote:
> Hier meine ISR:

Augenkrebs!

Ist ja klar, dass die Übertragung dann funktioniert. Dein CS bleibt für 
immer low. Du musst mal klären, ob der DMA completion Interrupt wirklich 
nach Abschluss des Multiword-Transfers kommt. Und ob das SPI erst das 
erste Wort sendet und die DMA erst dann das zweite Wort schreibt.


Mir ist was aufgefallen:

1
HRM page 9-6:
2
3
[...] With each transfer, the DMA address (stored in the DMA Start 
4
Address registers) increments relative to the data size. The address
5
increments by 1 for 8-bit data transfers, by 2 for 16-bit transfers, 
6
or by 4 for 32-bit transfers.

Dein Zähler ist auf 2, deine Größe auf 8Bit. Dein Buffer ist 2 mal 
16Bit. Aber das wird nicht im Zusammenhang mit dem Fehler stehen.

von Benjamin S. (recycler)


Lesenswert?

ich habe im blackfin.org Forum gelesen, dass der BF da ein wenig eigen 
ist und teilweise nicht aufhört bzw. der IRQ zu früh kommt. Genauso ist 
es bei mir. Werde morgen mal den Autobuffermodus verwenden.

Ich habe noch zwei andere Fragen:
- Wenn ich im Descriptormodus das Controllwörd auf 900D setze (8 Bit, 
DMA owner, IRQ on Completion, DMA_EN) dann kann ich den Dma über 
Spi_config | = 0x0001 starten. Bei 900C im Descriptor aber nicht. Weil 
im BF HRM 9-8 steht:

"If the descriptor block is the last one in a linked list or the
only one (that is, a standalone transfer sequence), the Next
Descriptor Pointer within the descriptor block must point
to a memory location that contains a data value with bit 15
set to 0 (0xxx xxxx xxxx xxxx). If bit 0 is a 1 (0xxx xxxx xxxx
xxx1), the DMA channel is still enabled, but stalled, and the
remaining FIFO values are not discarded. This allows the
DMA engine to finish transferring the remaining values in
the FIFO."

Punkt 1 habe ich erledigt. Aber wie ist es mit Punkt 2 (Bit 0 => 0)



- Am Ende des Descriptors soll er auf einen Wert von 0x0001 (Base+0 vgl 
HRM Bild 9-4) zeigen. Wenn ich das aber mache, kann ich den DMA nicht 
wieder starten.


------------
Vlt weiß einer noch was zu dieser späten Stunde - bis morgen.

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.