Forum: Mikrocontroller und Digitale Elektronik SPI Interrupt oder Polling


von Lars (Gast)


Lesenswert?

Hi,

ich möchte via SPI große Arrays übertragen, so dass ich überlege 
inwiefern eine interrupt-gesteuerte Datenübertragung Sinn macht. Der DMA 
Support wird für das SPI nicht unterstützt. Als Controller verwende ich 
den LPC1758.

In meinem Interrupt lese ich das Statusregister, cleare das 
Interruptregister und schreibe das nächste Byte in das SPDR Register, 
welches anschließend übertragen werden soll. Der Datentransfer 
funktioniert.
1
static unsigned char buffer[512]; 
2
3
void SPI_IRQHandler(void)
4
{
5
  unsigned int state = LPC_SPI->SPSR; 
6
  switch(state)
7
  {
8
  case SPISTATE_SPIF:
9
    if(pos < 512)
10
        LPC_SPI->SPDR = buffer[pos++]; 
11
    else
12
    {  //Datenübertragung beenden 
13
       LPC_SPI->SPDR;  //read dummy 
14
       SPI_SetCS(HIGH); 
15
    }
16
    break;
17
  }
18
  LPC_SPI->SPINT = SPIINT_SPIF; 
19
}

Aber macht das überhaupt wirklich Sinn, die Datenübertragung 
interrupt-basierend zu gestalten, weil der zeitliche Abstand zwischen 
dem Beenden des SPI-Interrupts und einem neuen SPI-Interrupt ist so 
kurz, dass mein Timer Interrupt beispielsweise in dieser Zeit gar nicht 
ausgelöst wird. Erst wenn der SPI Datentransfer beendet ist, 
funktioniert der Timer (Intervall: 1ms) wieder ordnungsgemäß.

Des Weiteren kann ich während der SPI Übertragungszeit auch keine andere 
Datenübertragung die interrupt-basierend erfolgt wie z.B. I2C anstoßen, 
weil sich die Interrupts von SPI und I2C sonst in die Querre kommen. Ich 
erhalte in einem solchen Fall beispielsweise zwar die richtige Anzahl an 
ausstehenden I2C Receive Interrupts, die allerdings verzögert statt 
finden. Die erhaltenen I2C Daten werden allerdings überschrieben, weil 
das I2C-Datenregister nur ein Byte aufnehmen kann. Die restlichen 
erhaltenen Bytes sind demnach 0xFF....

Ab welchem Zeitpunkt denkt ihr darüber nach, einen Datenübertragung 
interrupt-basierend zu machen? Und wie stellt ihr sicher, dass andere 
Schnittstellen in dieser Zeit nicht mittels Interrupts angesprochen 
werden?

Gruß
Lars

von hmm... (Gast)


Lesenswert?

Macht in meinen Augen nur Sinn wenn der Controller wesentlich schneller 
als die SPI betrieben wird. Ansonsten ist schlicht zu wenig Zeit 
zwischen zwei Interrupts in der man was anderes Sinnvolles tun kann. 
Sicher kann man durch geschicktes Priorisieren auch ander Interrupts 
noch abarbeiten,das verzögert aber den SPI Transfer zusätzlich. Macht 
also meistens keinen Sinn.

Und wenn man z.B. ein LCD möglichst schnell beschreiben will dürfte der 
Overhead um in den Interrupt zu springen mehr Relax generieren als wenn 
man auf ein Flag pollt.

Ab einem CPU Takt vom mindestens zehnfachen SPI Clock kann man drüber 
nachdenken.Besser wäre eine DMA sofern verfügbar und zwischendrin nicht 
am nCS gewackelt werden muss.

von Lars (Gast)


Lesenswert?

hmm... schrieb:
> Ab einem CPU Takt vom mindestens zehnfachen SPI Clock kann man drüber
> nachdenken.Besser wäre eine DMA sofern verfügbar und zwischendrin nicht
> am nCS gewackelt werden muss.

ja ich glaub werd auch erstmal wieder Abstand vom Interrupt beim SPI 
nehmen. Prozessor läuft zwar auf 100MHz und die SPI mit 10MHz, aber 
Polling scheint hier doch sinnvoller zu sein

von Rudolph (Gast)


Lesenswert?

Hmm, 10MHz SPI Takt und 100MHz CPU-Takt sind doch mindestens 80 
Taktzyklen die der Kern macht während der SPI-Transfer läuft.
Und dann kann man auch noch die Datenbreite hochsetzen.

Wenn da zwischen zwei SPI-Transfers nichts anderes passiert würde ich 
mal vermuten, dass da was falsch läuft.
Wie z.B. das der Interrupt nicht wieder freigegeben wird.

von Lars (Gast)


Lesenswert?

Rudolph schrieb:
> Und dann kann man auch noch die Datenbreite hochsetzen.

das ist richtig, man könnte bis zu 16 Bits übertragen.

Rudolph schrieb:
> Wenn da zwischen zwei SPI-Transfers nichts anderes passiert würde ich
> mal vermuten, dass da was falsch läuft.
> Wie z.B. das der Interrupt nicht wieder freigegeben wird.

eigentlich ist das alles sehr übersichtlich bei diesem Prozessor was die 
Register angeht. Bekomme auch keine Fehler im STatusregister angezeigt.

von Jim M. (turboj)


Lesenswert?

Lars schrieb:
> Der DMA Support wird für das SPI nicht unterstützt.

Dafür nimmt man besser die SSP Schnittstelle, die einen FIFO hat und DMA 
kennt. Eine davon liegt übrigens auf denselben Pins wie SPI, siehe auch 
UM10360.pdf, Kapitel 17.1.

Wegen dem FIFO muss man bei SSP allerdings das Datenregister immer lesen 
und schreiben.

Noch was:
1
LPC_SPI->SPINT = SPIINT_SPIF;

Das Rücksetzen des Interrup Flags darf nicht die letzte Anweisung in der 
Handler Function sein. Das funktioniert nicht, sobald der Compiler das 
optimiert. Hintergrund ist das Zusammenspiel von Write Buffer (1 Takt 
Verzögerung beim Schreiben) und Tail-Chaining - das dafür sorgt, das der 
Handler erneut aufgerufen würde.

Workaround: Zeile weiter nach oben schieben (vor das switch) oder
1
 NVIC_ClearPendingIRQ(SPI_IRQn);
als letzte Zeile einfügen.


Apropos switch: Dein switch(state) ist ungünstig, wenn mehrere Flags 
gesetzt werden. Das sollte besser ein
1
if( state & SPISTATE_SPIF )
sein.

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.