Forum: Mikrocontroller und Digitale Elektronik AT91SAM7X -SPI-Kommunikation über den PDC-


von Rafael L. (excalibur)


Lesenswert?

Hallo Leute,

ich habe wieder mal ein Problem mit meiner SPI - Schnittstelle genauer 
gesagt mit meinem PDC - Controller.

Also ich arbeite mit dem AT91SAM7X512 und will mit Hilfe der 
SPI-Schnittstelle und des PDC ein Datenframe der Größe 51Byte auf einmal 
übertragen. Sollte auch wirklich an einem Stück übertragen werden, da 
Byte 51 die CRC-Summe der anderen Bytes enthält.

Komischerweise kann ich an einem Stück nur ca. 20Byte übertragen. Bei 26 
Byte ist auf jeden Fall feierabend und der Controller hängt sich auf. 
Wie viel Bytes sollte ich eingentlich auf einmal mit SPI und PDC 
übertragen können??? Hat einer von euch schon mal ähnliche Probleme 
gehabt??? Wie habt ihr das Problem gelöst????

Ich setze ganz normal alle Zeiger, wie ich es auch hier im Forum schon 
mehrere male gesehen habe und kann mir das Verhalten nicht erklären....

        //disable
        pSPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;

        //* Initialize the Transmit and Receive Pointer
        pSPI->SPI_TPR = (unsigned int) txBuffer ;
        pSPI->SPI_RPR = (unsigned int) rxBuffer ;

        //* Intialize the Transmit and Receive Counters
        pSPI->SPI_RCR = (unsigned int)length;
        pSPI->SPI_TCR = (unsigned int)length;


        // trigger interrupt when the last byte was received!!
        pSPI->SPI_IER = AT91C_SPI_RXBUFF | AT91C_SPI_MODF;

        //enable transmitter and receiver
        AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;



Wäre über eure Hilfe wirklich sehr dankbar.....


Gruß
Rafael

von gerhard (Gast)


Lesenswert?

>Komischerweise kann ich an einem Stück nur ca. 20Byte übertragen. Bei 26
>Byte ist auf jeden Fall feierabend und der Controller hängt sich auf.
wie äussert sich das "aufhängen"?

>Wie viel Bytes sollte ich eingentlich auf einmal mit SPI und PDC
>übertragen können???
max. 64kbyte da der zähler nur 16 bit breit ist.

>Hat einer von euch schon mal ähnliche Probleme gehabt???
nein, pdc und spi funkt. ohne probleme.

>Wie habt ihr das Problem gelöst????
1) datenblatt gelesen
2) im datenblatt das kapitel errata gelesen.
3) die beispiele von atmel angesehen und die als ausgangsbasis verwendet 
und entspr. erweitert. speziell die reihenfolge der initialisierung der 
div. peripherie-bausteine ist wichtig.

gruss
gerhard

von Rafael L. (excalibur)


Lesenswert?

Hallo Gerhard,

danke erst mal für die schnelle Antwort.
Der Tip mit dem Datenblatt war echt super aber da hatte ich auch schon 
mal kurz reingesehen und steht ja leider nichts zu meinem Problem drin. 
Auch das Kapitel errata konnte mir dabei nicht helfen! LEIDER!!!!!

Ich hatte mir schon gedacht das ich mit den 16bit 65536 Byte schicken 
kann, wollte nur auf Nummer sicher gehen bzw. prüfen ob es da 
irgendwelche Einschränkungen gibt. Aber die scheint es ja nicht zu geben 
und das macht es noch komischer warum ich nicht mehr als 20Byte senden 
kann.

NA ja,.....
Also das Aufhängen äußert sich so, dass wenn ich mit einer for-Schleife 
nach dem Senden die Daten ausgeben will, die Ausgabe einfach stoppt und 
dann nicht mehr passiert.....

Ich weiß jetzt nicht ob mein Problem damit zusammenhängt, dass ich 
zusätzlich mit einem ECOS arbeite und ob das mir die Probleme macht. 
Kann ich mir aber eigentlich auch nicht vorstellen, da ich ja direkt auf 
dem PDC und der SPI-Schnittstelle arbeite.

Bin da im Momentwirklich ratlos.

Danke trotzdem.

Gruß
Rafael

von gerhard (Gast)


Lesenswert?

>Also das Aufhängen äußert sich so, dass wenn ich mit einer for-Schleife
>nach dem Senden die Daten ausgeben will, die Ausgabe einfach stoppt und
>dann nicht mehr passiert.....
ohne den source code zu sehen ist es schwer dir weiter zu helfen.

gruss
gerhard

von Rafael L. (excalibur)


Lesenswert?

Ja das nicht ganz so einfach mit dem Source, ist über einige Dateien 
verteilt aber versuche mal hier das wesentliche zusammen zu stellen.

Also die eigentliche Transmitmethode sieht so aus:

void spiTransmit(char channel, char *txBuffer, char *rxBuffer, unsigned 
short length)
{

    AT91PS_SPI pSPI = AT91C_BASE_SPI1; // pointer to a SPI controller

    spiTransLength = 0;

    if (spiRole == SPI_ROLE_MASTER) {
        //set the rigth chip select
        AT91F_SPI_CfgPCS(AT91C_BASE_SPI1, ~((char)1<<channel) );


        //disable
        pSPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;

        //* Initialize the Transmit and Receive Pointer
        pSPI->SPI_TPR = (unsigned int) txBuffer ;
        pSPI->SPI_RPR = (unsigned int) rxBuffer ;

        //* Intialize the Transmit and Receive Counters
        pSPI->SPI_RCR = (unsigned int)length;
        pSPI->SPI_TCR = (unsigned int)length;

        // trigger interrupt when the last byte was received!!
        pSPI->SPI_IER = AT91C_SPI_RXBUFF | AT91C_SPI_MODF;

        //enable transmitter and receiver
        AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;


    }
}

Die wird aufgerufen durch:

spiTransmit( ((struct spi_buf_t*)buf)->channelNum, ((struct 
spi_buf_t*)buf)->txBuffer, ((struct spi_buf_t*)buf)->rxBuffer, 
((struct spi_buf_t*)buf)->packetSize);

Die Struktur ist so aufgebaut:

struct spi_buf_t {
    char  *txBuffer;
    char  *rxBuffer;
    unsigned long packetSize;
    char channelNum;
    char driverMode;
};


Deklariert:

static struct spi_buf_t spiBuffer;

Initialisiert:

spiBuffer.channelNum = 1;
spiBuffer.packetSize = 51;
spiBuffer.txBuffer = daten;
spiBuffer.driverMode = POLLING_MODE;

Und daten ist ein Array der größe 51, also: char daten[51];


So das sollten eingentlich alle relevanten Daten sein und wie gesagt, 
wenn ich nur bis zu 20 Byte sende dann klappt auch alles.

Wenn ich jetzt aber spiBuffer.packetSize höher setze also versuche mehr 
als 20 Byte zu senden dann geht es nicht mehr. Warum?????

MFG
Rafael

von Rafael L. (excalibur)


Lesenswert?

Hallo......,

also das Problem mit dem PDC hat sich soweit geklärt!
Funktioniert ganz hervorragend!!!!!!!!!!!!

Das Problem lag gar nicht beim PDC sondern war wohl eine Verletzung des 
Speicherbereichs, die ich mir aber nicht erklären kann und vielleicht 
weiß jemand von euch ja woran das liegen kann!?!?!?!?

Also habe eine Struktur definiert:

struct spi_buf_t {
    char  *txBuffer;
    char  *rxBuffer;
    unsigned long packetSize;
    char channelNum;
    char driverMode;
};

Im weiteren wird dann eine Variable von dem Typ deklariert:

static struct spi_buf_t spiBuffer;

Und initialisiert:

Hier bei habe ich mehrere Sachen ausprobiert:

1.

spiBuffer.txBuffer = {1, 2, 3, 4, 5};
spiBuffer.rxBuffer = {0, 0, 0, 0, 0};

Hierbei wird direkt spiBuffer.txBuffer direkt von rxBuffer überschrieben 
und nachdem man einmal darüber nachgedacht hat ist das eigentlich auch 
klar. rxBuffer hat den Speicherbereich um eine Adresse zu speichern und 
nicht ein ganzes Array und deshalb wird hier txBuffer direkt 
überschrieben. So habe ich mir das zumindest erklärt.

2.

char senden[5];
char empfangen[5];

spiBuffer.txBuffer = senden;
spiBuffer.rxBuffer = empfangen;

War dann der zweite Versuch und eigentlich war ich der Meinung das es so 
auch funktionieren müßte! Hier werden erst zwei Arrays deklariert und 
initialisiert und später einfach die Zeiger auf diese Arrays gelegt.

Erste Test zeigten dann aber das in dem rxBuffer immer ein Byte mit 
einer Null beschrieben war und ich konnte mir nicht erklären warum. Es 
zeigte sich das direkt nach der Übergabe,

spiBuffer.txBuffer = senden;
spiBuffer.rxBuffer = empfangen;  ,

dieses Byte 0 war.

Hat zufällig jemand eine Idee warum????

3.

Lösung zu diesem Zeitpunkt war rxBuffer nichts zuzuweisen und den Zeiger 
so dem PDC zu übergeben. Und das funktionierte, aber nur bis zu einer 
Größe von 20 Byte die auf einmal gesendet wurden. Wenn mehr gesendet 
wurden dann gab es wohl die Speicherbereichverletzung und der Kontroller 
hat sich aufgehangen.


4.

Die derzeitige aktuelle Lösung ist:

spiBuffer.txBuffer = senden;

wird so ziehmlich am Anfang der Methode zugewiesen und

spiBuffer.rxBuffer = empfangen;

erst später im Programmverlauf, genauer gesagt in der while-Schleife.

Und das funktioniert. Jetzt kann ich mir vorstellen das der µC hier im 
Programmverlauf und damit auch mit seinem Speicherbereichen weiter ist 
und rxBuffer sowie txBuffer sich deshalb nicht mehr in die Quere kommen 
aber so ganz verstehe ich das nicht. Normal sollte es doch wie unter 2. 
beschrieben richtig funktionieren oder etwa nicht?????

Also falls jemand von euch da eine Idee oder die Lsg hat dann immer raus 
damit. Würde das ja ganz gerne verstehen um nicht wieder in so eine 
"Falle!" zu laufen und es nicht einfach so hinnehmen.

Also SPI funzt....... FREU

Gruß
Rafael

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.