Forum: Mikrocontroller und Digitale Elektronik Infineon XC886 CAN FIFO zum Senden


von Daniel Schwalm (Gast)


Lesenswert?

Hallo zusammen!

Ich versuche gerade einen Sende-FIFO für CAN-Nachrichten auf einem XC886 
zu implementieren. Dazu habe ich die 32 Message Objekte des XC886 wie 
folgt aufgeteilt:

0-7: Transmit-FIFO (Base Object: 0)
8-31: Receive-FIFO (Base Object: 8)

Zudem habe ich mir von Dave die Funktion CAN_ubWriteFIFO() generieren 
lassen. Diese Funktion rufe ich in folgender Funktion auf, welche das 
senden einer CAN-Nachricht kapselt:
1
void komSendeDaten( canDaten8Byte *canMessage )
2
{ 
3
  un_32bit  canDataObject;
4
  un_32bit  canIDObject;
5
  stCAN_SWObj canTransmitObject;
6
7
  canTransmitObject.ubMOdlc  = 0x08;                 // Data Length auf 8 Byte setzen
8
  canTransmitObject.ubMOcfg  = 0xAA;              // Config-Bits setzen
9
10
  canIDObject.ulVal       = canMessage->lCanId;      // neue CAN-ID aufbauen
11
  canTransmitObject.ulID     = canIDObject;             // ID in CAN Objekt laden
12
13
  canDataObject.ubDB[0]     = canMessage->cDaten[3];      // neue low CAN-Daten aufbauen
14
  canDataObject.ubDB[1]     = canMessage->cDaten[2];
15
  canDataObject.ubDB[2]     = canMessage->cDaten[1];
16
  canDataObject.ubDB[3]     = canMessage->cDaten[0];
17
  canTransmitObject.ulDATAL   = canDataObject;
18
19
  canDataObject.ubDB[0]     = canMessage->cDaten[7];      // neue high CAN-Daten aufbauen
20
  canDataObject.ubDB[1]     = canMessage->cDaten[6];
21
  canDataObject.ubDB[2]     = canMessage->cDaten[5];
22
  canDataObject.ubDB[3]     = canMessage->cDaten[4];
23
  canTransmitObject.ulDATAH   = canDataObject;
24
25
//  CAN_vConfigMsgObj( TRANSMIT_OBJECT, &canTransmitObject );   // CAN-Objekt in Message Object laden
26
//  CAN_vTransmit(TRANSMIT_OBJECT);               // Sende-Prozess starten
27
28
  CAN_ubWriteFIFO(TRANSMIT_OBJECT, &canTransmitObject);    // Das zu sendente CAN-Paket in den Transmit FIFO einreihen
29
}

Nun habe ich das Problem, dass der Controller 8 CAN-Nachrichten sendet 
und danach nichts mehr. Also einmal wird jedes der 8 Message-Objekt des 
Transmit-FIFO zum senden genutzt und sobald der CUR-Zeiger wieder auf 
das erste Message Objekt zeigt, sendet der Controller nichts mehr. Die 
Funktion CAN_ubWriteFIFO() gibt aber weiterhin ein 1 zurück (was 
eigentlich auf korrekte Funktion deuten sollte). Ich habe die Vermutung, 
dass ich nach dem Senden irgendwas an den Message-Objekten 
"umkonfigurieren" oder zurücksetzen muss. Leider bin ich mit Debugging 
und so weiter noch nicht dahinter gekommen, was das ist... In einem 
Beispiel-Code (ich glaube von Infineon) wird aber auch nichts anderes 
gemacht, als die Funktion CAN_ubWriteFIFO() aufzurufen (konnte ich 
leider nicht testen, da ich die Hardware dafür nicht habe). Wenn ich den 
Aufruf von CAN_ubWriteFIFO() auskommentiere und statt dessen die zwei 
Zeilen darüber reinnehme, funktioniert das Senden dauerhaft (allerdings 
ohne FIFO). Vielleicht hat ja jemand eine Idee, woran das FIFO-Problem 
liegen könnte? Evtl. auch ein Fehler in der Funktion CAN_ubWriteFIFO()?

Viele Grüße,
Daniel

von Daniel Schwalm (Gast)


Lesenswert?

Manchmal geht es schneller als man denkt ;) Hab nun herausgefunden, 
woran das Problem lag. Hier ein kurzer Bericht, für alle die evtl. mal 
vor dem selbigen stehen:

Der Fehler lag nicht in meiner Funktion sondern in der von Dave 
erzeugten Funktion CAN_ubWriteFIFO() und zwar an folgender Stelle:
1
...
2
        CAN_vWriteCANAddress(CAN_MOCTR(j));
3
        CAN_vReadEN();   // Readmode is Enabled
4
5
        if((CAN_DATA1 & 0x01)== 0x00)  // if reset TXRQ
6
        {
7
            if(j == CAN_DATA3)  // last MO in a list
8
            {
9
               // WritePtr = BOT of the base object
10
               CAN_vWriteCANAddress(CAN_MOFGPR(ubObjNr));
11
               CAN_vReadEN();   // Readmode is Enabled
12
               aubFIFOWritePtr[ubObjNr] = CAN_DATA0;
13
            }
14
            else
15
            {
16
               // WritePtr = PNEXT of the current selected slave
17
               aubFIFOWritePtr[ubObjNr] = CAN_DATA3;
18
            }
19
20
            CAN_vWriteCANAddress(CAN_MOCTR(j));  // Addressing CAN_MOCTRn register
21
            CAN_vWriteCANData(0x00000008);      // reset NEWDAT
22
...

Hier soll eigentlich sichergestellt werden, dass wenn das letzte 
Message-Objekt des Sende-FIFOs gerade zum Senden genutzt werden soll, 
dass bei der nächsten Sendeanforderung wieder das erste Objekt genutzt 
wird. Dies wird in aubFIFOWritePtr[ubObjNr] gespeichert. Leider prüft 
die Funktion nicht ob das aktuelle Objekt das letzte im FIFO ist sondern 
ob es das letzte in der Liste ist! D.h. mein FIFO geht von den Objekten 
0-7, die Liste aber von 0-31 (da die Liste auch den Empfangs-FIFO 
beinhaltet). Also wurde versucht, nachdem 8 Pakete gesendet wurden, das 
Message Objekt 8 zum senden zu nutzen, was aber ein Receive Message 
Object ist!

Hier die überarbeitet Version, die auf den ersten Blick bei mir wie 
gewünscht funktioniert:
1
...
2
        CAN_vWriteCANAddress(CAN_MOCTR(j));
3
        CAN_vReadEN();   // Readmode is Enabled
4
5
        if((CAN_DATA1 & 0x01)== 0x00)  // if reset TXRQ
6
        {
7
      CAN_vWriteCANAddress(CAN_MOFGPR(ubObjNr));    // Zeiger-Register des Base-Objektes laden
8
          CAN_vReadEN();   // Readmode is Enabled
9
      
10
            if(j == CAN_DATA1)  // prufen ob letztes MsgObj im Sende-FIFO (=TOP-Objekt)
11
            {
12
               // WritePtr = BOT of the base object
13
               CAN_vWriteCANAddress(CAN_MOFGPR(ubObjNr));
14
               CAN_vReadEN();   // Readmode is Enabled
15
               aubFIFOWritePtr[ubObjNr] = CAN_DATA0;
16
            }
17
            else
18
            {
19
               // WritePtr = PNEXT of the current selected slave
20
         CAN_vWriteCANAddress(CAN_MOCTR(j));
21
             CAN_vReadEN();   // Readmode is Enabled
22
               aubFIFOWritePtr[ubObjNr] = CAN_DATA3;
23
            }
24
25
            CAN_vWriteCANAddress(CAN_MOCTR(j));  // Addressing CAN_MOCTRn register
26
            CAN_vWriteCANData(0x00000008);      // reset NEWDAT  - OK, Funktioniert!
27
...

Die Änderung besteht eigentlich nur darin, dass nicht auf das Ende der 
Liste sondern auf das Ende des FIFOs geprüft wird (Vergleich mit dem 
TOP-Zeiger des Transmit-FIFO Base-Objektes).

Ich hoffe das ich damit anderen ein paar Stunden Fehlersuche ersparen 
konnte ;)

Viele Grüße,
Daniel

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.