GPIO und SPI bei ATSAM2D asynchron?

Gast #6283230
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!
Gast #6283256
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
Gast #6283292
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!
Moderator Persönliche Seite #6283304
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.
Gast #6283310
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren