On 07/25/2010 05:08 PM, Wolfgang Grandegger wrote:
> On 07/25/2010 04:23 PM, Wolfgang Grandegger wrote:
>> On 07/25/2010 03:35 PM, Marc Kleine-Budde wrote:
>>> Wolfgang Grandegger wrote:
>>>> I found some time to work on this issue.
>>>>
>>>> So far we only report CAN error state changes to the worse:
>>>> "error-active -> error-warning -> error-passive -> bus-off", but not
>>>> "bus-off -> error-active" or "error-passive -> error-warning ->
>>>> error-active". There have been request from other users to correct
>>>> this behavior.
>>>>
>>>> This patch reports any state change reported by the SJA1000 and
>>>> MSCAN-MPC5200 controller. It introduces "CAN_ERR_CRTL_ACTIVE" to
>>>> signal state changes to error active. Furthermore, the SJA1000
>>>> triggers now the bus-off recovery procedure when restarted. So far,
>>>> the controller was *stopped* and then restarted. I did two tests to
>>>> analyze the state changes behavior:
>>>>
>>>> 1. First I forced the controller into the error-passive by sending
>>>> a message (with cansend) without cable connected (*). Then I
>>>> reconnected the cable (**) and continued to send messages (with
>>>> cangen) (***) until the error active state is reached:
>>>>
>>>> On SJA1000:
>>>>
>>>> # candump any,0:0,#FFFFFFFF
>>>> (*)
>>>> can0 20000004 [8] 00 08 00 00 00 00 60 00 ERROR-WARNING
>>>> can0 20000004 [8] 00 20 00 00 00 00 80 00 ERROR-PASSIVE
>>>> (**)
>>>> can0 123 [4] DE AD BE EF
>>>> (***)
>>>> can0 42A [1] 00
>>>> ...
>>>> can0 42A [1] 07
>>>> can0 20000004 [8] 00 08 00 00 00 00 7F 00 ERROR-WARNING
>>>
>>> Is it possible to tell apart whether the driver goes from passive to
>>> warning or from active to warning? Without the need to have a state
>>> machine in userspace, too?
>>
>> Yes, I realized that side effect as well. The user must monitor state
>> changes to understand if the state gets worse or better. We could use an
>> error bit to indicate state improvements.
>>
>>> Looking at the tx/rx error level might be an option, but I've seen that
>>> the level can rise very quickly.
>>
>> Be aware that the tx/rx error counters are *not* readable on all CAN
>> controllers.
>>
>>>> can0 42A [1] 08
>>>> ...
>>>> can0 42A [1] 27
>>>> can0 20000004 [8] 00 40 00 00 00 00 5F 00 ERROR-ACTIVE
>>>> \-- tx-err !!!
>>>> On MSCAN:
>>>>
>>>> # candump any,0:0,#FFFFFFFF
>>>> (*)
>>>> can2 20000004 [8] 00 08 00 00 00 00 00 00 ERROR-WARNING
>>>> can2 20000004 [8] 00 20 00 00 00 00 00 00 ERROR-PASSIVE
>>>> (**)
>>>> can2 123 [4] DE AD BE EF
>>>> can2 20000004 [8] 00 08 00 00 00 00 00 00 ERROR-WARNING
>>>> (***)
>>>> can2 42A [1] 00
>>>> can2 42A [1] 01
>>>> ...
>>>> can2 42A [1] 1E
>>>> can2 42A [1] 1F
>>>> can2 20000004 [8] 00 40 00 00 00 00 00 00 ERROR-ACTIVE
>>>>
>>>> As you can see, the state change to error-active is signaled
>>>> differently. The MSCAN seems not to respect the specs :-(.
>>>
>>> Do you mean the fact that error active is signalled with tx err == 0?
>>
>> Yes, the SJA1000 triggers an interrupt to signal error active when the
>> error counter goes below 96.
>>
>>> From the patch below you only changed the part of the driver that runs
>>> if a change of state is detected "(old_state != priv->can.state)".
>>>
>>> Maybe it's a problem in the driver, that calculated the new state wrong.
>>> Maybe due to a problem with the hardware. (I don't know the driver nor
>>> the hardware).
>>
>> I monitored the interrupt generation as well:
>>
>> [ 1234.089446] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x44)
>> [ 1234.092228] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x48)
>> [ 1240.960487] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x44)
>> [ 1352.336647] mpc5xxx_can f0000900.can: error interrupt (canrflg=0x40)
>>
>> The last interrupt comes that late, even if the state is misinterpreted.
>> Note also that the MSCAN has a dedicated state field for TX and RX.
>> Therefore the state is defined without a state machine in software.
>>
>>> Looking at you patches below I want to rise my old proposal again. I
>>> think we should move the state machine that assembles and sends the
>>> error frames into a common function. Each driver just needs to have a
>>> proper function that calculates the current state and then call the
>>> state handling state machine.
>>
>> The error handling code is already quite large and complex, especially
>> for the purpose it serves. Any common function improving that situation
>> would be nice. But unfortunately, we rely on the hardware :-(.
>>
>>>> When time permits, I will also try the MSCAN of the MPC5121.
>>>
>>>> 2. I forced the controller into bus-off by short-circuiting
>>>> the low and hi lines and sending a message (*), Then I
>>>> restarted the controller manually with
>>>> "ip link set can0 type can restart" (**):
>>>>
>>>> On SJA1000:
>>>>
>>>> # ./candump -t d any,0:0,#FFFFFFFF
>>>> (*)
>>>> can0 20000004 [8] 00 08 00 00 00 00 88 00 ERROR-WARNING
>>>> can0 20000004 [8] 00 20 00 00 00 00 88 00 ERROR-PASSIVE
>>>> can0 20000044 [8] 00 00 00 00 00 00 7F 00 BUS-OFF
>>>> (**)
>>>> can0 20000100 [8] 00 00 00 00 00 00 00 00 RESTARTED
>>>> can0 20000004 [8] 00 40 00 00 00 00 00 00 ERROR-ACTIVE
>>>> \-- tx-err !!!
>>>>
>>>> On MSCAN:
>>>>
>>>> # ./candump -t d any,0:0,#FFFFFFFF
>>>> (*)
>>>> can2 20000004 [8] 00 08 00 00 00 00 00 00 ERROR-WARNING
>>>> can2 20000040 [8] 00 00 00 00 00 00 00 00 BUS-OFF
>>>> (**)
>>>> can2 20000100 [8] 00 00 00 00 00 00 00 00 RESTARTED
>>>> can2 20000004 [8] 00 40 00 00 00 00 00 00 ERROR-ACTIVE
>>>>
>>>> The MSCAN seems not to signal the ERROR-PASSIVE state before
>>>> going bus-off.
>>>
>>> I think the signalling of ERROR-PASSIVE depends on multiple things:
>>> - the current bitrate.
>>> I think this doesn't count so much in this short circuit test.
>>> - the CAN hardware itself: does it signal this "in-the-middle-passive"
>>> interrupt
>>> - overall speed and load of your system:
>>> reaction time on interrupts,
>>> is your system fast enough to handle these two back-to-back interrupts
>>> as two single events
>>> - driver design, i.e.
>>> - is the state change signalled from the hard-irq or from napi:
>>> the second interrupt may occur somewhere between hardirq and napi,
>>> so napi just sees bus off
>>> - design of the error state machine:
>>> in the at91 and flexcan I always send a warning interrupt if going
>>> from active to passive.
>>>
>>> The last point is another argument for a common state machine.
>>
>> Well, yes, a common state handling function would be nice, but as the
>> hardware is not really smart, a simple state machine is not enough. It's
>> not just reading the current state and check if it has changed. Have a
>> look to the SJA1000 and MSCAN driver, e.g.:
>>
>> if (isrc & IRQ_EPI) {
>> /* error passive interrupt */
>> dev_dbg(dev->dev.parent, "error passive interrupt\n",
>> status);
>> if (status & SR_ES) {
>> if (priv->can.state == CAN_STATE_ERROR_WARNING)
>> state = CAN_STATE_ERROR_PASSIVE;
>> else
>> state = CAN_STATE_ERROR_WARNING;
>> } else {
>> state = CAN_STATE_ERROR_ACTIVE;
>> }
>> }
>>
>> No need for another state machine. But a common function is still useful
>> to fill an error frame for the state change, of course. I will try to
>> come up with a proposal soon.
>
>
> int can_handle_state_change(struct net_device *dev,
> struct can_frame *cf,
> enum can_state new_state,
> u16 tx_err, u16 rx_err)
>
> If "tx_err" or "rx_err == -1", they are ignored. If "new_state ==
> CAN_STATE_UNKNOWN", the state could be derived from tx_err or rx_err.
> What do you think?
This message was sent accidentally. Sorry for the noise.
Wolfgang.
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core