mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Blackfin GPIO rising edge


Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

mein BF537 stellt mich gerade vor ein Kuriosum. Es geht dabei um den 
Port F (PF2 bis PF5) GPIO über den ich die Taster von meinem EZ-Kit auf 
steigende Flanke prüfen möchte. Im ersten Schritt konfigurierte ich die 
betreffenden Pins des GPIO's:
void Init_Flags(void)
{
  // ...
  *pPORTF_FER = 0x0000;
  *pPORTF_FER = 0x0000;

  // set PORTF direction register
  *pPORTFIO_DIR = 0x1FC0;
     //EZ-Kit switches as Input (PF5..2), LEDs (PF6..11) as Output

  // set PORTF input enable register
  *pPORTFIO_INEN = 0x003C;
     //EZ-Kit switches enable Input (PF5..2), LEDs as Output (PF6..11)

  //set PORTF polarization register
  *pPORTFIO_POLAR = 0x0020;
     //EZ-Kit switch SW10 is active low (bypass switch)

  //set PORTF edge register
  *pPORTFIO_EDGE = 0x001C;
     //EZ-Kit switches SW11-13 are rising edge sensitive

  // set PORTF clear register
  *pPORTFIO_CLEAR = 0x0FC0 & 0x0FC0;
     //EZ-Kit LEDs off
}

Hier geht es erstmal um den Switch SW11 und SW12 (PF4 und PF3) zum 
testen. Anschließend strickte ich mir eine einfache Abfrage in der die 
LED1 mit SW11 an und mit SW12 wieder ausgeschaltet werden sollte:
//...
#define FUNCTION 4
#define DOWN     3
// ...

void main(void)
{
  Init_Flags();
  // ...

  while(1)
  {
    if( *pPORTFIO & (1 << FUNCTION) )      // rising edge?
    {
      *pPORTFIO_SET = (1 << 6) & 0x0FC0;   // LED6 on
      *pPORTFIO_CLEAR = (1 << FUNCTION);   // (1)
    }
    else if( *pPORTFIO & (1 << DOWN) )
    {
      *pPORTFIO_CLEAR = (1 << 6) & 0x0FC0; // LED6 off
      *pPORTFIO_CLEAR = (1 << DOWN);       // (1)
    }
  }
}

(1) "For GPIOs configured as edge-sensitive, a readback of 1 from one
    of these registers is sticky. That is, once it is set it remains set
    until cleared by user code. [...]" (Hardware Reference page 14-12)

Das funktionierte leider nicht. Die LED geht weder an (und 
logischerweise auch nicht wieder aus  ;^) ). Also versuchte ich es 
hiermit:
//...
#define FUNCTION 4
#define DOWN     3
// ...

void main(void)
{
  Init_Flags();
  // ...

  while(1)
  {
    if( *pPORTFIO & (1 << FUNCTION) )      // rising edge?
    {
      *pPORTFIO_SET = (1 << 6) & 0x0FC0;   // LED6 on
    }
    else if( *pPORTFIO & (1 << DOWN) )
    {
      *pPORTFIO_CLEAR = (1 << 6) & 0x0FC0; // LED6 off
    }

    *pPORTFIO_CLEAR = (1 << FUNCTION);
    *pPORTFIO_CLEAR = (1 << DOWN);
  }
}

Und siehe da, es klappt; Aber nicht perfekt, d.h. manchmal mit etwas 
Verzögerung - eher marginal, aber für einen 600MHz Prozessor doch 
deutlich zu langsam. Lösche ich die pPORTFIO_CLEAR Register nicht so 
bleibt die LED (wie zu erwarten) an, nehme ich die "else"-Anweisung weg 
dann flackert sie - das macht alles Sinn. Ich sollte noch erwähnen, dass 
ein Interrupt mit 48kHz ausgelöst wird in dem bisher ein paar einstufige 
IIR's und ein mächtiger 1300er FIR durchgezogen werden (alles fractional 
1.15). Wo liegt der Fehler? Habe ich etwas übersehen/vergessen zu 
setzen?

  pumpkin



Edit:
Was mich stutzig macht ist der folgende Abschnitt in der Hardware 
Reference (page 1-11):

"GPIO interrupt sensitivity registers – The two GPIO interrupt 
sensitivity
registers specify whether individual pins are level- or edge-sensitive 
and specify—if edge-sensitive—whether just the rising edge or both the 
rising and falling edges of the signal are significant. One register 
selects the type of sensitivity, and one register selects which edges 
are significant for edge-sensitivity."

Plötzlich ist von Interrupt-Registern die Rede (sicher kann man damit 
welche auslösen, aber ist das nicht etwas inkonsistent formuliert?).

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Lösungen, vllt bringt es ja irgendwann jemanden weiter:

ASM Stil:
//...
#define FUNCTION 4
#define DOWN     3
// ...

void main(void)
{
  // ...

  while(1)
  {
    if( *pPORTFIO & (1 << FUNCTION) )
    {
      asm("P0.L = 0x0708; ");      //#
      asm("P0.H = 0xFFC0; ");      //# PORTFIO_SET
      asm("R0.L = 0x0040; ");
      asm("W[P0] = R0;    ");

      asm("P0.L = 0x0704; ");      // PORTFIO_CLEAR
      asm("R0.L = 0x0010; ");
      asm("W[P0] = R0;    ");
    }
    else if( *pPORTFIO & (1 << DOWN) )
    {
      asm("P0.L = 0x0704; ");      //#
      asm("P0.H = 0xFFC0; ");      //# PORTFIO_CLEAR
      asm("R0.L = 0x0048; ");
      asm("W[P0] = R0;    ");
    }
  }
}


C Stil:
//...
#define FUNCTION 4
#define DOWN     3
// ...

void main(void)
{
  // ...

  while(1)
  {
    if( *pPORTFIO & (1 << FUNCTION) )
    {
      *pPORTFIO_SET = (1 << 6);
      *pPORTFIO_CLEAR = (1 << FUNCTION);
    }
    else if( *pPORTFIO & (1 << DOWN) )
    {
      *pPORTFIO_CLEAR = (1 << 6);
      *pPORTFIO_CLEAR = (1 << DOWN);
      asm("NOP; ");                  // !!!
    }
  }
}

Mit dem kleinen NOP in C steht und fällt die Sache. Ich habe bisher 
nicht begriffen warum, im disassembly konnte ich bisher keine 
Unterschiede feststellen.  %^/

VisualDSP++ 4.5, May 2006


pumpkin

Autor: Xion (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nicht mit Interrupt routinen?

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da muss ich nur wieder gucken wie der mir in meinen Audio-Interrupt 
reinknallt uswusf. - ist mir (bei diesem Wetter ; ) ) zu anstrengend, 
vllt in der nächsten Version.

Viel interessanter ist imho der Umstand mit NOP. ssync() oder 
asm("SSYNC;") haben nichts gebracht. Die Errata/IC Anomaly bringt 
diesbezüglich auch nichts gescheites für den 537 hervor. 
http://www.blackfin.org hilft leider auch nicht. Die Compiler Errata hab 
ich noch nicht gewälzt - aber ich denke es liegt an ihm.


pumpkin

Autor: Xion (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf gar keinen Fall ich arbeite jetz seit 2 Jahre mit Blackfin 
Prozessoren ich hab leider nicht viel zeit deine Programm zu 
nachvollziehen aber ich kann dir mit 99.99% Sicherheit sagen das es dein 
Fehler ist. Hast du überhaupt die PLL richtig intialisiert? Ich denke 
auch eines seits es ist ein Denkfehler eine Edge detecting per Polling 
zu entdeken um diese auszuschließen solltest du vielleicht eine Level 
detecting versuchen.

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke nicht, dass ich einen Denkfehler habe - in ASM funktioniert 
mein Ansatz einwandfrei. Wieso sollte es ein Fehler sein einen 
Trigger-Latch (Hardware!) per polling zu dedektieren? Ich habe mir die 
Geschichte mit dem Interrupt durchdacht und bin zu dem Schluss gekommen, 
dass es für meine Anwendung vorerst nicht in Frage kommt.

Ich habe ein Beispiel von VisualDSP verwendet, insofern stellt sich die 
Frage nach der PLL für mich nicht - aber guter Tip, ich werde dem mal 
nachgehen. Vielmehr stellt sich für mich die Frage ob du in C/C++ oder 
ASM programmierst und ob du dich schonmal mit solch einer Konfiguration 
beschäftigt hast.

Ich habe auch mit keiner Silbe erwähnt, dass der Blackfin einen Fehler 
macht - Die Errata beäugen war nur ein logischer Schritt bei der 
Fehlersuche.

pumpkin

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.