cancel
Showing results for 
Search instead for 
Did you mean: 

CAN baud rate change, device is restarting continuously!

ramji
Associate II

Facing issue with CAN baud rate change!
1. The Master and slave devices are communicating at baud rate of 1Mbps.
2. If I change the baud rate of Master device to any other baud rate(like, 250kbps, 500kbps,125kbps,50kbps) then master device contiguously restarting the device! Got to know that, it is restarting due to watch dog timer!
3. To resolve the restart issue, added the timeout logic in the while loop where it is entering into intialize mode and normal mode.
4. I gave CAN_TIMEOUT as 1000ms, If I add timeout logic, device is not communicating with slave and data is not exchanging due while timeout logic
5. Tried with different logic by calling HAL_NVIC_SystemReset(); in the timeout logic.

static UINT32 CanFunctin(void)
{
         UINT32 tickstart = 0,tickstart1=0;
        // static UINT32 BaudRateChange=0;
         UINT32 error=0;
// Exit Sleep mode and enter Initialize mode.
CAN1->MCR &= ~CAN_MCR_SLEEP;
CAN1->MCR |= CAN_MCR_INRQ;

        tickstart = FPGA_GET_FRT_UINT32;
// Wait for Initialize mode acknowledge.
while ((CAN1->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
{
          if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
          {
              uint32_t esr = CAN1->ESR;
              printf("Err-CanPortInit: Timeout waiting to enter initi mode\n");
              if (esr & CAN_ESR_BOFF) printf("CanPortInit - Bus-Off condition detected\n");
              if (esr & CAN_ESR_EPVF) printf("CanPortInit - Error Passive mode\n");
              if (esr & CAN_ESR_EWGF) printf("CanPortInit - Error Warning level reached\n");
              return error;
          }
}
CAN1->MCR |= CAN_MCR_ABOM;  // Auto Bus-Off Management
// Initialize Master Control Register.
CAN1->MCR |= MCR_INZ;

// Initialize CAN bit timing.
CAN1->BTR = BTR_INZ | CanBaud[CanBaudRate] | SJW_INZ(CanSjw);
if (CAN1->ESR & CAN_ESR_BOFF)
{
     CAN1->ESR = 0;  // Clear error flags
}
    // Enter Normal mode.
    CAN1->MCR &= ~CAN_MCR_INRQ;
    tickstart1 = FPGA_GET_FRT_UINT32;

// Wait for Normal mode acknowledge.
while ((CAN1->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
 {
          if ((HAL_GetTick() - tickstart1) > CAN_TIMEOUT_VALUE)
          {
              uint32_t esr = CAN1->ESR;
              printf("Err-CanPortInit: Timeout waiting to enter NORMAL mode\n");
              if (esr & CAN_ESR_BOFF) printf("CanPortInit - Bus-Off condition detected\n");
              if (esr & CAN_ESR_EPVF) printf("CanPortInit - Error Passive mode\n");
              if (esr & CAN_ESR_EWGF) printf("CanPortInit - Error Warning level reached\n");
              error=1;
              CAN1->ESR = 0;
              RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST;
              RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST;
              __NOP(); __NOP(); __NOP();
              HAL_NVIC_SystemReset();
               CAN1->ESR = 0;
              return error;
          }
}
// Enable CAN interrupt sources.
CAN1->IER = IER_INZ;
      return error;
}

Thank you in advance for any suggestions!



7 REPLIES 7
ramji
Associate II

Merger thread. Please don't duplicate the same subject on separated threads.

Hello,

I’m using STM32F746 with CAN1 peripheral in Normal mode, and facing an issue during runtime:

  • when the master and slave device communicate at baud rate of 1Mbps and if I change the baud rate of master device to any other baud rate then then gets stuck in a while loop waiting for Normal Mode acknowledgment:

 

// Enter Normal Mode
CAN1->MCR &= ~CAN_MCR_INRQ;
while ((CAN1->MSR & CAN_MSR_INAK) == CAN_MSR_INAK); // stuck here

What I've Done:

  • I perform a software reset before reinitializing CAN:

     
    RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST;
    RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST;
  • I cleared the BUS-OFF condition manually:

     
    if (CAN1->ESR & CAN_ESR_BOFF)
    { CAN1->ESR = 0; }
  • I enabled auto bus-off recovery:

     
    CAN1->MCR |= CAN_MCR_ABOM;
  • CAN is configured in Normal mode, with filters set and interrupts enabled.

Problem:

After the master changes its baud rate, the STM32 re-initializes, but hangs at the wait for Normal mode acknowledge.

Question:

  • Is there something else needed to recover cleanly from this situation?

  • Do I need to delay or detect bus idle before exiting INIT mode?

  • Any additional register I should clear or sequence to follow?

Any suggestions or official guidance would be appreciated.

mƎALLEm
ST Employee

Hello,

I invite you to use the HAL and do your preliminary tests before using the direct access to the registers.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Ozone
Principal

> Facing issue with CAN baud rate change!

What do you actually mean here ?
CAN does not support a dynamic baudrate change in the network (leaving out CAN-FD and CAN-XL here).

> // Wait for Normal mode acknowledge.

What an acknowledge you are waiting for here ?
Those only come when another node responds to a sent message.

Do you have any node on your network beside the F7 board at all ?
Without another node, it will never work.

if (esr & CAN_ESR_BOFF) printf("CanPortInit - Bus-Off condition detected\n");
if (esr & CAN_ESR_EPVF) printf("CanPortInit - Error Passive mode\n");
if (esr & CAN_ESR_EWGF) printf("CanPortInit - Error Warning level reached\n");
...
HAL_NVIC_SystemReset();

Those CAN errors do NOT require a MCU reset.
Especially if your node is master device (in a CAN-Open context), a MCU reset is not alwaysthe right way to go.
A NMT-Reset is sufficient.

Thanks for the clarification!

To confirm:

  • Yes, we have a master and a slave on the CAN bus.

  • We are using the STM32F746 with an external CAN transceiver(82C251).

Regarding the acknowledgment:
We’re waiting for the CAN peripheral to exit initialization mode (monitoring CAN_MSR & CAN_MSR_INAK), not expecting a message ACK from the bus.

Initially, we attempted an MCU reset (NVIC_SystemReset()) as a recovery method,  even I tried by enabling CAN_MCR_ABOM.

Thank you!

While I deal quite a bit with CAN and also with STM32 device, I have not used CAN on STM32 yet.
Other people in my company choose the hardware / ECUs.

In short, you would need to read the F7 reference manual for the exact meaning of those CAN peripheral status flags.

> Yes, we have a master and a slave on the CAN bus.

Use a PC CAN adapter and some basic monitoring software to see what's happening. You will need it.
PCAN adapters are relatively inexpensive, and a basic CAN monitoring software is available without charge.

> Initially, we attempted an MCU reset (NVIC_SystemReset()) as a recovery method,  ...

That I have seen.
The errors you tried to remedy with a reset are the result of failed CAN bus transmission. This is what the Tx / Rx error counters reflect, which result in reaching first the "error passive" and then the "bus off" level.

Perhaps your bus settings (timing parameters) are wrong, or the other CAN node does not use the baudrate you assume. Use a scope and check the digital signals on the CAN Tx/Rx pins of the STM32 (or input of the CAN transceiver), and on the bus itself.


On a side note ...
CAN does not employ a "master / slave" concept. Message arbitration happens by the CAN ID (address), not originating node.
Only some higher-level protocols based upon CAN (like CanOpen) employ such an idea, although not strictly.

Thank for response!

Do you want me to try anything?

Well, you are sitting in front of the system, and want find the cause.
I would try both - check the CAN signals of the STM32 and on the bus via scope, and use a PC can node (in listen-only mode) to monitor if it reports errors.
The latter makes limited sense if there is no CAN bus signal.

You haven't forgotten the termination resistor by chance ?
And you can try to swap the CAN_H and CAN_L on one node, this does no harm to the hardware.
A CAN_GND connection is recommended, but in many cases not strictly necessary.