Forum: Mikrocontroller und Digitale Elektronik [STM32] CAN Bus: Fehlende RAM Zuweisung für TX FIFO ?


von CAN-Liebhaber (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

Ich kämpfe seit einiger Zeit damit, den CAN-Bus auf meinen zwei 
Evalboards (STM32H745I-DISCO) zum Laufen zu bringen. Um das ganze zu 
testen möchte ich, dass das eine Evalboard dem anderen eine Nachricht 
sendet. Die Abschlusswiderstände habe durch setzen der Jumper 
berücksichtigt. Die beiden Evalbaords habe ich jeweils über CAN-High und 
CAN-Low mit einander verbunden.

Das Problem: Ich komme gar nicht erst soweit, dass ich was senden kann: 
Egal wie ich den CAN-Bus in CubeMX konfiguriere, das Programm springt 
immer in den folgenden Fehlerabschnitt, in dem anscheinend geprüft wird 
ob dem TX FIFO Speicher im RAM zugewiesen wurden ist (zumindest steht es 
so im Kommentar):
1
   /* Check that the Tx FIFO/Queue has an allocated area into the RAM */
2
    if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
3
    {
4
      /* Update error code */
5
      hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
6
 
7
      return HAL_ERROR;
8
    }

Der oben erwähnte Abschnitt kommt aus der stm32h7xx_hal_fdcan.c.

Meine CAN-Bus Konfiguration sieht wie folgt aus. Erst einmal habe ich 
das FDCAN Initialisiert:
1
static void MX_FDCAN1_Init(void)
2
{
3
  hfdcan1.Instance = FDCAN1;
4
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
5
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
6
  hfdcan1.Init.AutoRetransmission = ENABLE;
7
  hfdcan1.Init.TransmitPause = DISABLE;
8
  hfdcan1.Init.ProtocolException = DISABLE;
9
  hfdcan1.Init.NominalPrescaler = 12;
10
  hfdcan1.Init.NominalSyncJumpWidth = 1;
11
  hfdcan1.Init.NominalTimeSeg1 = 5;
12
  hfdcan1.Init.NominalTimeSeg2 = 2;
13
  hfdcan1.Init.DataPrescaler = 12;
14
  hfdcan1.Init.DataSyncJumpWidth = 1;
15
  hfdcan1.Init.DataTimeSeg1 = 5;
16
  hfdcan1.Init.DataTimeSeg2 = 2;
17
  hfdcan1.Init.MessageRAMOffset = 0;
18
  hfdcan1.Init.StdFiltersNbr = 1;
19
  hfdcan1.Init.ExtFiltersNbr = 0;
20
  hfdcan1.Init.RxFifo0ElmtsNbr = 16;
21
  hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
22
  hfdcan1.Init.RxFifo1ElmtsNbr = 0;
23
  hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
24
  hfdcan1.Init.RxBuffersNbr = 16;
25
  hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
26
  hfdcan1.Init.TxEventsNbr = 16;
27
  hfdcan1.Init.TxBuffersNbr = 16;
28
  hfdcan1.Init.TxFifoQueueElmtsNbr = 16;
29
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
30
  hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
31
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
32
  {
33
    Error_Handler();
34
  }

Anschließend kommt die Konfiguration von RX und TX. Abschließend starten 
ich den CAN-Bus:
1
  /* Configure Rx filter */
2
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
3
  sFilterConfig.FilterIndex = 0;
4
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;
5
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
6
  sFilterConfig.FilterID1 = 0x456; 
7
  sFilterConfig.FilterID2 = 0x7FF;
8
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
9
  {
10
    Error_Handler();
11
  }
12
13
  /* Configure Tx Settings */
14
  TxHeader.Identifier = 0x123; 
15
  TxHeader.IdType = FDCAN_STANDARD_ID;           
16
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;       
17
  TxHeader.DataLength = FDCAN_DLC_BYTES_2;       
18
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;  
19
  TxHeader.BitRateSwitch = FDCAN_BRS_OFF;       
20
  TxHeader.FDFormat = FDCAN_CLASSIC_CAN;             
21
  TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; 
22
  TxHeader.MessageMarker = 0;
23
 
24
  /* Start FDCAN bus */
25
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
26
  {
27
    Error_Handler();
28
  }

So weit so gut: bisher habe ich keinen Error zurückbekommen. Scheint als 
wäre die Initialisierung und Konfiguration erfolgreich gewesen. Nun 
versuche ich eine Nachricht zu senden:
1
FDCAN_HandleTypeDef hfdcan1;
2
FDCAN_FilterTypeDef sFilterConfig;
3
FDCAN_TxHeaderTypeDef TxHeader;
4
uint8_t TxData[8]={0xCC,0xDD};
5
 
6
int main(void)
7
{
8
 ...
9
 
10
  MX_GPIO_Init();
11
  MX_FDCAN1_Init();
12
 
13
  while (1)
14
  {
15
      if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
16
      {
17
        Error_Handler();
18
      }
19
      HAL_Delay(1000);
20
  }
21
}

Die Funktion
1
 HAL_FDCAN_AddMessageToTxFifoQ
 springt dann in den Fehlerabschnitt, den ich ganz oben im Thread 
erwähnt habe, und liefert einen HAL_ERROR zurück. Was mache ich falsch? 
Sieht die Konfiguration des CAN-Bus denn einigermaßen richtig aus oder 
liege ich damit schon vollkommen daneben? Der Vollständigkeit halber 
habe ich die Quellcodes in den Anhang gepackt.

Würde mich riesig über ein paar nützliche Hinweise und Tipps freuen. 
Danke euch im Voraus!

von CAN-Liebhaber (Gast)


Angehängte Dateien:

Lesenswert?

Was vielleicht auch ganz interessant ist: Der Fehlerabschnitt (ich nenne 
ihn einfach mal so...) prüft die markierten Bits im TXBC-Register (siehe 
Bild im Anhang). Die Bits sind durchgehend Null. Laut Beschreibung unten 
im Bild bedeutet das, dass es keine TX FIFO/queue gibt, was nicht sein 
kann, denn ich habe ein TX-Buffer von 16 angegeben... Wo ist mein 
Denkfehler?

von M. Н. (Gast)


Lesenswert?

CAN-Liebhaber schrieb:
> Die Bits sind durchgehend Null.

Das ist nicht gut. Das bedeutet, dass zumindest kein TX FIFO/Queue 
konfiguriert wurde. Sind die anderen Angaben konfiguriert? Sind die 16 
dedizierten TX Buffer konfiguriert? Kannst du über die dedizierten 
Puffer etwas senden?

Gemäß User manual:
https://www.bosch-semiconductors.com/media/ip_modules/pdf_2/m_can/mcan_users_manual_v330.pdf

müsste das eigentlich alles soweit tun. Ist der Message RAM im STM auch 
groß genug für die ganzen Puffer?

von CAN-Liebhaber (Gast)


Lesenswert?

Hallo M.H.,

danke für deine Antwort. Wie ein wunder funktioniert das Senden jetzt 
doch! Ich hab am Code selber nie was geändert. Das einzige was ich 
gemacht habe war ein Mass Erase und dann die gleiche SW nochmal 
geflasht. Nun sehe ich meine Nachrichten die ich Sende auf dem Bus!

M. H. schrieb:
> Ist der Message RAM im STM auch groß genug für die ganzen Puffer?

Ja, der Puffer ist für 64 Elemente ausgelegt. Ich verwende nur 16.

Was mich allerdings etwas wundert ist, dass die Nachrichten nicht im 
RX-Buffer abgelegt werden. Die SW ist auf beiden Evalboards identisch 
mit der Ausnahme der FilterID1 und des TX-Identifier logischerweise. Ich 
hab jetzt folgende Zeilen hinzugefügt:
1
    if ((phfdcan1->Instance->RXF0S & FDCAN_RXF0S_F0FL) != 0U) //Check wheather FIFO is not empty
2
    {
3
        if  (HAL_FDCAN_GetRxMessage(&hfdcan1,FDCAN_RX_FIFO0, &RxHeader, RxData)!= HAL_OK)
4
        {
5
          Error_Handler();
6
        }
7
    }

Das andere Evalboard sendet Nachrichten mit der TX-ID 0x456 und Mask-ID 
ist 0x7FF. Müsste ich nicht den Inhalt der Nachricht dann in dem Array 
"RxData" wiedersehen? Hoffe die Frage passt noch inhaltlich in den 
Thread rein ...

von Joe J. (j_955)


Lesenswert?

Hallo,
eine Ergänzung noch:
gabs nicht im Errata noch irgendwas zum Thema CANfd?
...guck dir das mal bei der CPU auf jeden Fall mal durch, falls du beide 
CANFD Interfaces brauchst.
Jo

von CAN-Liebhaber (Gast)


Lesenswert?

Joe J. schrieb:
> falls du beide CANFD Interfaces brauchst.

Nein ich brauche nur ein CAN-Interface von jeweils einem Evalboard, 
falls du das damit meinst.

von Joe J. (j_955)


Lesenswert?

Nein, ich meine für die Anwendung/das Produkt...falls das für dich 
relevant ist.

: Bearbeitet durch User
von CAN-Liebhaber (Gast)


Lesenswert?

Verstehe, danke für den Hinweis ist aber erst einmal nicht relevant. 
Aktuell verstehe ich noch nicht ganz wieso meine gesendeten Nachricht 
nicht ins RX-FIFO gelangen. Hab ich die Filtermaske falsch eingestellt? 
Ich check's nicht...

von CAN-Liebhaber (Gast)


Lesenswert?

Nochmal eine Frage zum allgemeinen Verständnis: ein Busteilnehmer sendet 
zyklisch Nachrichten mit der ID 0x456, also genau auf die ID, welche ich 
im RX-Filter eingestellt habe (siehe erster Post). Wird dann die 
Nachricht vom Empfänger automatisch in das "Empfänger-FIFO" hinterlegt 
und ich muss sie nur noch mit
1
HAL_FDCAN_GetRxMessage
 abholen oder ist meine Vorstellungen falsch? Wenn ja, dann verstehe ich 
nicht wieso das FIFO beim Empfänger ständig leer ist. Dabei sehe ich die 
CAN Nachricht auf dem Bus mit dem Logicanalyzer, sie enthält die 
richtige ID und Payload...

von Jens R. (tmaniac)


Lesenswert?

Hast du schon einmal versucht den Empfangsfilter komplett offen zu 
lassen?

Also ich gehe bei deiner Beschreibung davon aus, dass du einen 
Testaufbau hast und noch kein Netzwerk das dich mit Nachrichten 
bombardiert.

Um den Empfang sicher zu konfigurieren fängt man in der Regel ohne 
Filter an.

Zu den Filtern: ich habe "nur" einen STM32F4 mit bxCAN aber hier muss 
man aufpassen, weil die Bits RTR und IDE am unteren Ende der 32bit Maske 
sind.
Deine CanId und MaskId müssten also 3bit nach links geschoben werden.

Verzeih mir wenn mir das STM32H7 Manual etwas zu dick zum nachschauen 🙈

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.