CAN High Level Driver States

Use this forum for requesting small changes in ChibiOS. Large changes should be discussed in the development forum. This forum is NOT for support.
Post Reply
neums
Posts: 137
Joined: Fri May 08, 2015 1:09 pm
Has thanked: 10 times
Been thanked: 5 times

CAN High Level Driver States

Post by neums »

Hi,
in the documentation of the CAN driver's state machine are transitions from CAN_STARTING and READY to itselfs by calling canStart(). In code it is an illegal call/transition due to osalDbgAssert

Code: Select all

void canStart(CANDriver *canp, const CANConfig *config) {

  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert(canp->state == CAN_STOP, "invalid state");

Is this a bug?
Thanks
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: CAN High Level Driver States

Post by Giovanni »

Hi,

It looks like a bug, I will look into it, queued for next release.

Giovanni
neums
Posts: 137
Joined: Fri May 08, 2015 1:09 pm
Has thanked: 10 times
Been thanked: 5 times

Re: CAN High Level Driver States

Post by neums »

Hi,
thanks for your help.
How i can restart the CAN when it is gone into BUS OFF without using the automatic bus off management (ABOM)?
I know that i can stop and start it again. But in the context where i want to restart it the CANConfig structure is not available due to my software structure. May it is a good feature to have a function which just restarts the driver or writes the RESET bit in MCR? So the configuration is unaffected but the CAN gets reset.

Thanks
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: CAN High Level Driver States

Post by Giovanni »

Hi,

All drivers keep a pointer to the configuration structure internally, do not assume that the structure is no more required after starting the driver, some drivers could incidentally work but the structure is supposed to be persistent.

Giovanni
neums
Posts: 137
Joined: Fri May 08, 2015 1:09 pm
Has thanked: 10 times
Been thanked: 5 times

Re: CAN High Level Driver States

Post by neums »

So a restart can be done with

Code: Select all

canStart(&CAND1,&CAND1->config)

where the reset bit is set in the mcr register of the config structure?
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: CAN High Level Driver States

Post by Giovanni »

canStart reinitializes the CAN controller, see INRQ bit in the STM32 RM, then MCR is initialized again.

Giovanni
neums
Posts: 137
Joined: Fri May 08, 2015 1:09 pm
Has thanked: 10 times
Been thanked: 5 times

Re: CAN High Level Driver States

Post by neums »

OK that is the first way. But why not reset the CAN controller with an procedure like this:

Code: Select all

// clear all transmit mailboxes
canp->can->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
// reset CAN controller by setting the RESET BIT which is cleared again by hardware
canp->can->MCR |= CAN_MCR_RESET;

In this procedure the CANConfig structure is not needed because of the canStart call. So the user can reset the CAN controller in case of CAN High-Low short without the availability of the CANConfig structure which is required by canStart.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: CAN High Level Driver States

Post by Giovanni »

To be placed where?

Giovanni
neums
Posts: 137
Joined: Fri May 08, 2015 1:09 pm
Has thanked: 10 times
Been thanked: 5 times

Re: CAN High Level Driver States

Post by neums »

Something like this in the LLD:

Code: Select all

void can_lld_reset_controller(CANDriver *canp) {
// clear all transmit mailboxes
canp->can->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
// reset CAN controller by setting the RESET BIT which is cleared again by hardware
canp->can->MCR |= CAN_MCR_RESET;
}

and this in HLD:

Code: Select all

void canResetController(CANDriver *canp) {
  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
                "invalid state");

  can_lld_reset_can_controller(canp);

  osalSysUnlock();
}


And if it makes sence an I-class function to reset the controller from the error callback.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: CAN High Level Driver States

Post by Giovanni »

Moving topic.

Giovanni


Last bumped by Giovanni on Sun Jan 06, 2019 5:09 pm.
Post Reply