Forum: Mikrocontroller und Digitale Elektronik GPIO und SPI bei ATSAM2D asynchron?


von Sortland (Gast)


Lesenswert?

Hi,

ich versuche mit folgendem Code 24 Datenbits per SPI auszugeben, wobei 
sich die beiden SPI-Geräte ein gemeinsames CS-Signal teilen:
1
    gpio_set_pin_level(DAC_CS,false); // CS auf LOW ziehen
2
3
    // 3x 8 bit per SPI ausgeben und jeweils darauf warten, dass SERCOM damit fertig wird:
4
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[3]); //SPI2
5
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[3]); //SPI4
6
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_RXC))
7
8
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[2]); //SPI2
9
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[2]); //SPI4
10
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_RXC))
11
12
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[1]); //SPI2
13
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[1]); //SPI4
14
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_RXC))
15
16
    gpio_set_pin_level(DAC_CS,true); // CS wieder auf HIGH setzen

Was ich erwarten würde, was passiert:

- CS-Leitung geht auf LOW
- ich sehe 24 Clock-Pulse auf der SPI-Taktleitung
- CS-Leitung geht auf HIGH

Was statt dessen passiert:

- CS-Leitung geht auf LOW
- für ca 220 nsec passiert nichts
- ich sehe 17 Clock-Pulse auf SCLK
- CS geht auf HIGH
- es kommen die fehlenden 7 Clock-Pulse

Also scheint da mit meiner Synchronisation was nicht zu stimmen? Mit 
welchem Registerbit überwache ich denn wirklich, ob alle Datenbits 
gesendet wurden? RXC scheint es ja nicht zu sein...

Danke!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

TXC sollte das sein (im Unterschied zu DRE, welches nur besagt, dass du 
weitere Daten ins Ausgaberegister schreiben kannst).

von Sortland (Gast)


Lesenswert?

TXC macht es nur anders aber nicht besser. Dann ist das Ergebnis

- CS geht auf LOW
- ca 22 nsec nichts
- 8x SCLK
- ca. 550 nsec nichts
- 8x SCLK
- ca 550 nsec nichts
- 6x SCLK
- CS geht auf HIGH
- 2x SCLK

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zwischen den Bytes brauchst du kein TXC benutzen, da genügt DRE.

Ansonsten hat TXC für uns seinerzeit funktioniert (auf einem SAMR21, 
aber das ist letztlich ein modifizierter SAMD21 mit einem AT86RF233 
drüber gestapelt).

von Sortland (Gast)


Lesenswert?

OK, das Problem scheint auch wo anders zu liegen. Wenn ich folgende 
Funktion habe:
1
static void SPI_ExchangeBuffer(const uint8_t pSendX[4],const uint8_t pSendY[4])
2
{
3
    gpio_set_pin_level(DAC_CS,false); // CS auf LOW ziehen
4
5
    // 3x 8 bit per SPI ausgeben und jeweils darauf warten, dass SERCOM damit fertig wird:
6
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[3]); //SPI2
7
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[3]); //SPI4
8
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_DRE))
9
10
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[2]); //SPI2
11
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[2]); //SPI4
12
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_DRE))
13
14
    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[1]); //SPI2
15
    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[1]); //SPI4
16
    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_TXC))
17
18
    gpio_set_pin_level(DAC_CS,true); // CS wieder auf HIGH setzen
19
}

dann wird das Setzen von DAC_CS am Ende nicht ausgeführt. Rufe ich 
gpio_set_pin_level(DAC_CS,true) vor dem Verlassen der Funktion aber zwei 
mal auf, dann funktioniert es und ich sehe, dass CS auf HIGH geht.

Ähnliches passiert beim Beschreiben der DATA-Register: nur einer der 
beiden SERCOMs zeigt mir 24 Clock-Bits, beim anderen werden nur 8 
ausgegeben. Verdopple ich die Aufrufe von 
hri_sercomspi_write_DATA_reg(), dann sendet auch der andere SPI 24 Bits.

Wenn das Lesen der Statusbits genau so zuverlässig funktioniert, ist es 
klar, dass das Timing nicht stimmt.

Erzeugt habe ich den Code mit Atmel START, bauen tue ich im AtmelStudio 
unter Windows. Ist das ein Compilerproblem oder habe ich irgend was 
anderes blödes übersehen, was dieses Verhalten verursachen könnte?

Danke!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vielleicht solltest du ja auch, wenn du auf zwei SERCOMs arbeitest, auf 
jeder von beiden das DRE-Bit testen?

START / FSF haben wir nie benutzt, irgendwie zu aufgebläht und 
obfuscated. Wir haben uns lowlevel-Routinen selbst geschrieben (hat auch 
den Vorteil, dass sich bspw. auch ein STM32Fxxx da parallel ganz gut 
einbinden lässt).

Keine Ahnung, ob da noch was vergurkt sein könnte – eigentlich haben 
sich die Jungs und Mädels da Mühe gegeben, jeden auch noch so obskuren 
Fall abzudecken, aber ich habe (als ich mir das mal für irgendeinen 
eigenen Code als Vorlage genommen habe) da auch schon Bugs entdeckt. War 
allerdings nicht SAMD/SAMR, sondern SAM4E/SAME70.

: Bearbeitet durch Moderator
von foobar (Gast)


Lesenswert?

>
1
>    hri_sercomspi_write_DATA_reg(SERCOM2,pSendX[1]); //SPI2
2
>    hri_sercomspi_write_DATA_reg(SERCOM1,pSendY[1]); //SPI4
3
>    while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM1) & SERCOM_SPI_INTFLAG_TXC))
4
         ;
5
>    gpio_set_pin_level(DAC_CS,true); // CS wieder auf HIGH setzen
6
>

Dürfte an den fehlenden Semikola liegen.

Davon abgesehen: ich würde mich nicht darauf verlassen, dass die beiden 
SERCOMs gleichzeitig fertig sind - besser beide testen.

von Sortland (Gast)


Lesenswert?

foobar schrieb:
> Dürfte an den fehlenden Semikola liegen.

Oh F***, na klar, Danke!!!

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.