Forum: Mikrocontroller und Digitale Elektronik MKE02(Arm Cortex m0+) SPI Communication TxBuffer wird nicht auf Shiftregister kopiert


von A. G. (archy404)


Angehängte Dateien:

Lesenswert?

Guten Tag,

Ich versuche gerade eine SPI-Kommunikation zwischen dem ESP32S3 und 
einem MKE02 MCU (FRDM_KE02Z40M EVA-Board) herzustellen. Leider verhält 
sich das Programm nicht so wie es soll und ich bin mir nicht sicher ob 
der Fehler bei mir liegt (vermutlich schon) oder das SPI-Modul auf dem 
Board fehlerhaft ist.

Der ESP32S3 sendet als Master 32 Byte an Daten. Das FRDM_KE02Z40M Board 
sollte 32 Byte zurück senden.

Allerdings, obwohl die Daten, welche vom ESP32S3 gesendet werden korrekt 
beim FRDM Board ankommen, wird nur das erste Byte, welches der MKE02 MCU 
schicken soll übertragen. Nach dem ersten Byte erhält der ESP32S3 nur 
ein Echo seiner eigenen Nachricht. (Das Freedom Board sollte hier z.B. 
zu testzwecken 0xBB 32 mal schicken)

Daten gesendet vom ESP32S3:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F

Daten die der MKE02Z (FRDM-Board) schicken sollte:

BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB
BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB

Daten Empfangen vom ESP32S3:

BB 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E


Der relevante Code der ISR sieht wie folgt aus:
1
void spi_slave_irq(spi_handle_t *handle){
2
uint8_t flags = spi_getStatusRegister();
3
//Check wether the Transmit Buffer empty flag is set and if so, write the next 8 bit to SPI0_D
4
if(((flags & 0xFFU) & SPI_S_SPTEF_MASK) != 0)
5
{
6
spi_write_shiftregister(*(handle->txData));
7
handle->txData++;
8
handle->txindex++;
9
}
10
//Check wether the Recieve Buffer full flag is set and if so, read the next 8 bit from SPI0_D
11
if(((flags & 0xFFU) & SPI_S_SPRF_MASK) != 0)
12
{
13
*(handle->rxData) = spi_read_shiftregister();
14
handle->rxData++;
15
handle->rxindex++;
16
}
17
...

Es gibt eine RxBuffer und eine TxBuffer Flag, diese werden gesetzt, 
sollte der entsprechende mit dem Shiftregister verbundene Buffer 
Voll(rx)/Leer(tx) sein.

Das Shiftregister wird zuverlässig alle 8bit in den Buffer kopiert, die 
RxBuffer Full Flag wird zuverlässlich während der Übertragung gesetzt, 
die ISR gestartet und die Daten aus dem Buffer herauskopiert.

Allerdings wird die TxEmpty Flag während einer Übertragung NIE gesetzt, 
die TxFlag wird ausschließlich vor oder nach einer Übertragung gesetzt. 
Also wenn der ESP startet, dann wird die TXFlag gesetzt, der Buffer 
gefüllt, der Buffer direkt in das Shiftregister kopiert und die Flag 
erneut gesetzt. Dann wird das nächste Byte in den Buffer kopiert und das 
System idled bis eine Übertragung beginnt.

Ich habe die Vermutung, dass der mit dem Shiftregister verbundene Buffer 
während einer übertragung, also während der ss low ist nicht auf das 
Shiftregister kopiert wird. [ESP_SPI_MODELL.jpg]

Das würde in sofern Sinn machen, als dass die Daten, welche der ESP32S3 
auf das MKE-Shiftregister geshifted hat, bestehen bleiben würden, sollte 
der MKE02Z nicht neue Daten auf das Register kopieren. Dass hätte genau 
den besagten Effekt, dass das erste nach dem Start auf das Register 
kopierte Byte korrekt übertragen wird und jedes weitere Byte eine Kopie 
der Daten vom ESP32S3 ist.

Wenn ich die Kommunikation durch den ESP32 nach jedem Byte unterbreche 
und für das nächste Byte eine neue Kommunikation starte, werden die 
Daten korrekt übertragen. (Logic Analyzer Screenshot, in diesem Test 
sendet der ESP32 die Hexzahlen von 0 bis 1F, der MKE sendet diese 
ebenfalls)[Workaround.png]

Ich habe versucht eine Skizze der Funktionsweise des SPI-Moduls zu 
erstellen, wie ich Sie aus dem Reference Manual herausgelesen habe. 
Meiner Ansicht nach, funktioniert wie gesagt das Kopieren des TxBuffers 
auf das Shiftregister nicht, während der Slave Select low 
ist.[ESP_SPI_MODELL.jpg]
Der beschriebene Fehler tritt mit 2 baugleichen FRDM Evaluation Boards 
genau gleich auf. Der Fehler tritt auf, mit meinem selbstgeschriebenen 
Treiber, so wie mit dem bereitgestellten Freescale Treiber der Firma NXP 
und dem Treiber auf CMSIS Basis (auch von NXP)


Ist euch ein entsprechender Fehler schon einmal vorgekommen? Ist es 
möglich, dass ein entsprechender Fehler des SPI-Moduls nicht aufgefallen 
wäre?

Ich habe nach Datenblatt und Reference Manual keinen direkten Zugriff 
auf den mit dem SPI0_D Register verbundenen Buffer. Ich kann lediglich 
auf das "Register" zugreifen.

Ich danke euch vielmals für eure Erfahrung und hoffe ihr könnt mir 
erklären, ob der Fehler an mir liegt oder wirklich das verbaute SPI 
Modul
einen Funktionsfehler haben könnte.

von Jim M. (turboj)


Lesenswert?

Schau Dir nochmal genau den CS an. Einmal im Dabla was er machen soll, 
einmal was er wirklich auf der Hardware tut.

Üblicherweise schickt man den CS nicht nach jedem Byte auf High 
zurück...

von Michael D. (nospam2000)


Lesenswert?

A. G. schrieb:
> *(handle->rxData) = spi_read_shiftregister();

Hast du dir spi_read_shiftregister() man angesehen?

  Michael

von A. G. (archy404)


Lesenswert?

Hallo Michael,
vielen Dank, für die schnelle Antwort!

ja, bin beide Treiber mehrfach durchgegangen. Die Funktion ist aber auch 
nicht Fehleranfällig denke ich. Allerdings bin ich noch sehr neu was 
Hardwarenahe Programmierung angeht.
1
void spi_write_shiftregister(uint8_t data){
2
  spi0_registers->D = data;
3
}
4
5
uint8_t spi_read_shiftregister(void){
6
  return (uint8_t)spi0_registers->D;
7
}

Wie auf dem Diagramm zu sehen sollte die entsprechende read/write dann 
mit dem Buffer verbunden sein welcher wiederum mit dem Schieberegister 
verbunden ist.

von A. G. (archy404)


Angehängte Dateien:

Lesenswert?

Hallo Jim,
auch an dich Danke für deine Zeit.

Genau das denke ich auch. Im Datenblatt sind die entsprechenden Zeiten 
einer Kommunikation aufgelistet und ein Graphisches Modell der 
Kommunikation.
Der Graphischen Darstellung zufolge ist der SS durchgehend auf Low (was 
ja auch einfach standard ist bei SPI). [Charakteristische_Zeiten.png 
Graphische_Darstellung.png]

Im SPI Kapitel des <<Reference Manual>> steht genau folgendes zum SS als 
Slave:

<<
29.2.4 SS — Slave Select
When the SPI is enabled as a slave, this pin is the low-true slave 
select input.
>>

<<
29.4.3 Slave mode
[...]
• SS pin
The SS pin is the slave select input. Before a data transmission occurs, 
the SS pin of
the slave SPI must be low. SS must remain low until the transmission is 
complete. If
SS goes high, the SPI is forced into an idle state.
>>

Das die Kommunikation "funktioniert" wenn ich Sie als Bastellösung nach 
jedem Byte unterbreche und neu starte würde ich ungern als Lösung 
anwenden.

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.