STM32F205VG CAN Bus-Off recovery problem

Gast #4606419
Lesenswert?
• ▲
▼
Hi,

I have a problem with CAN after a bus-off condition.
When CAN state changes to bus-off, I set the CAN operation mode to SLEEP 
mode.
After a few 100 ms I try to bring the CAN bus into NORMAL mode again and 
then the Interrupts are activated again.
But it seems like the ESR register isn't cleard before CAN starts 
working and so I get a bus-off interrupt immediately after a restart... 
this is a never ending cycle.

1) Bus-Off Interrupt occurs
2) Disable CAN-Interrupts
3) Set Sleep-Mode (clear INRQ, set SLEEP in MCR Register)
4) Wait for SLAK bit set
5) Reset TX and RX Mailboxes/FIFOs, Clear all pending Interrupts
6) Wait for a few 100 ms
7) Enter Init-Mode (clear SLEEP, set INRQ, in MCR Register)
8) Wait for INAK Bit set
9) Enter Normal-Mode (clear SLEEP, clear INRQ in MCR Register)
10) Wait for INAK Bit cleared
11) Enable CAN-Interrupts
12) ---> SCE Interrupt --> BOFF Flag set --> Back to 1)

When I put an ASSERT((can->ESR & BOFF_BIT) == 0) immediately after 10), 
the assertion fails. But if put a breakpoint at the assertion and I 
check the register, all bits are cleared. And when I resume, it starts 
working as expected.

The Code for changing the CAN-Mode:
1
static tCanStatus SetCanMode(tCAN * can, tCanMode mode)
2
{
3
  uint32_t timeout = TIMEOUT_VALUE;
4

5
  if (mode == CAN_MODE_INIT)
6
  {
7
      can->MCR = (uint32_t)((can->MCR & (uint32_t)(~(uint32_t)CAN_MCR_SLEEP)) | CAN_MCR_INRQ);
8

9
      while (((can->MSR & CAN_MODE_MASK) != CAN_MSR_INAK) && (timeout != 0))
10
        timeout--;
11

12
      if ((can->MSR & CAN_MODE_MASK) != CAN_MSR_INAK)
13
        return CAN_STATUS_ERROR;
14
  }
15
  else if (mode == CAN_MODE_NORMAL)
16
  {
17
    can->MCR &= (uint32_t)(~(CAN_MCR_SLEEP | CAN_MCR_INRQ));
18

19
    while (((can->MSR & CAN_MODE_MASK) != 0) && (timeout != 0))
20
      timeout--;
21

22
    if ((can->MSR & CAN_MODE_MASK) != 0)
23
      return CAN_STATUS_ERROR;
24

25
    configASSERT((can->ESR & 0x04) == 0);    // Fails after a bus-off
26
  }
27
  else if (mode == CAN_MODE_SLEEP)
28
  {
29
    can->MCR = (uint32_t)((can->MCR & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
30

31
    while (((can->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK) && (timeout != 0))
32
      timeout--;
33

34
    if ((can->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK)
35
      return CAN_STATUS_ERROR;
36
  }
37

38
  return CAN_STATUS_OK;
39
}
Gast #4609395
Lesenswert?
• ▲
▼
Thank you.
I figured that out already. It seems like i misinterpreted the the Notes 
in the datasheet. I have to wait extra time after beeing in normal mode 
until CAN is synchronized with the bus. But i thought waiting until the 
CAN_MCR_INRQ bit is cleard already includes the synchronization...

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.