Skip to content

Commit 867fd92

Browse files
authored
Add non-ISO CANFD support to kvaser (#1752)
* Add basic non-iso support * Update test_kvaser.py Add unit test * Update test_kvaser.py Black to pass premerge checklist * Made code changes New enum for non-iso mode Documentation sections fixes Test update * Update bus.py Black cleanup
1 parent 621cd7d commit 867fd92

File tree

5 files changed

+55
-3
lines changed

5 files changed

+55
-3
lines changed

can/bus.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class CanProtocol(Enum):
4444
"""The CAN protocol type supported by a :class:`can.BusABC` instance"""
4545

4646
CAN_20 = auto()
47-
CAN_FD = auto()
47+
CAN_FD = auto() # ISO Mode
48+
CAN_FD_NON_ISO = auto()
4849
CAN_XL = auto()
4950

5051

can/interfaces/kvaser/canlib.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,10 @@ def __init__(
428428
computer, set this to True or set single_handle to True.
429429
:param bool fd:
430430
If CAN-FD frames should be supported.
431+
:param bool fd_non_iso:
432+
Open the channel in Non-ISO (Bosch) FD mode. Only applies for FD buses.
433+
This changes the handling of the stuff-bit counter and the CRC. Defaults
434+
to False (ISO mode)
431435
:param bool exclusive:
432436
Don't allow sharing of this CANlib channel.
433437
:param bool override_exclusive:
@@ -453,6 +457,7 @@ def __init__(
453457
accept_virtual = kwargs.get("accept_virtual", True)
454458
fd = isinstance(timing, BitTimingFd) if timing else kwargs.get("fd", False)
455459
data_bitrate = kwargs.get("data_bitrate", None)
460+
fd_non_iso = kwargs.get("fd_non_iso", False)
456461

457462
try:
458463
channel = int(channel)
@@ -461,7 +466,11 @@ def __init__(
461466

462467
self.channel = channel
463468
self.single_handle = single_handle
464-
self._can_protocol = CanProtocol.CAN_FD if fd else CanProtocol.CAN_20
469+
self._can_protocol = CanProtocol.CAN_20
470+
if fd_non_iso:
471+
self._can_protocol = CanProtocol.CAN_FD_NON_ISO
472+
elif fd:
473+
self._can_protocol = CanProtocol.CAN_FD
465474

466475
log.debug("Initialising bus instance")
467476
num_channels = ctypes.c_int(0)
@@ -482,7 +491,10 @@ def __init__(
482491
if accept_virtual:
483492
flags |= canstat.canOPEN_ACCEPT_VIRTUAL
484493
if fd:
485-
flags |= canstat.canOPEN_CAN_FD
494+
if fd_non_iso:
495+
flags |= canstat.canOPEN_CAN_FD_NONISO
496+
else:
497+
flags |= canstat.canOPEN_CAN_FD
486498

487499
log.debug("Creating read handle to bus channel: %s", channel)
488500
self._read_handle = canOpenChannel(channel, flags)

doc/interfaces/pcan.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ Here is an example configuration file for using `PCAN-USB <https://www.peak-syst
3737
``bitrate`` (default ``500000``)
3838
Channel bitrate
3939

40+
ISO/Non-ISO CAN FD Mode
41+
~~~~~~~~~~~~~~~~~~~~~~~
4042

43+
The PCAN basic driver doesn't presently allow toggling the ISO/Non-ISO FD modes directly.
44+
The default mode is stored on the device and can be controlled using the PCANView Windows application.
45+
See: https://forum.peak-system.com/viewtopic.php?t=6496
46+
47+
This restriction does not apply to the socket-can driver.
4148

4249
.. _pcandoc linux installation:
4350

doc/interfaces/socketcan.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ to ensure usage of SocketCAN Linux API. The most important differences are:
284284
:members:
285285
:inherited-members:
286286

287+
ISO/Non-ISO CAN FD Mode
288+
-----------------------
289+
290+
Socket CAN devices can (for supported hardware) control ISO vs Non-ISO FD during creation with the ``ip`` command using the ``fd-non-iso`` flag.
291+
287292
.. External references
288293
289294
.. _Linux kernel docs: https://www.kernel.org/doc/Documentation/networking/can.txt

test/test_kvaser.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def test_can_timing(self):
196196
def test_canfd_timing(self):
197197
canlib.canSetBusParams.reset_mock()
198198
canlib.canSetBusParamsFd.reset_mock()
199+
canlib.canOpenChannel.reset_mock()
199200
timing = can.BitTimingFd.from_bitrate_and_segments(
200201
f_clock=80_000_000,
201202
nom_bitrate=500_000,
@@ -210,6 +211,32 @@ def test_canfd_timing(self):
210211
can.Bus(channel=0, interface="kvaser", timing=timing)
211212
canlib.canSetBusParams.assert_called_once_with(0, 500_000, 68, 11, 10, 1, 0)
212213
canlib.canSetBusParamsFd.assert_called_once_with(0, 2_000_000, 10, 9, 8)
214+
canlib.canOpenChannel.assert_called_with(
215+
0, constants.canOPEN_CAN_FD | constants.canOPEN_ACCEPT_VIRTUAL
216+
)
217+
218+
def test_canfd_non_iso(self):
219+
canlib.canSetBusParams.reset_mock()
220+
canlib.canSetBusParamsFd.reset_mock()
221+
canlib.canOpenChannel.reset_mock()
222+
timing = can.BitTimingFd.from_bitrate_and_segments(
223+
f_clock=80_000_000,
224+
nom_bitrate=500_000,
225+
nom_tseg1=68,
226+
nom_tseg2=11,
227+
nom_sjw=10,
228+
data_bitrate=2_000_000,
229+
data_tseg1=10,
230+
data_tseg2=9,
231+
data_sjw=8,
232+
)
233+
bus = can.Bus(channel=0, interface="kvaser", timing=timing, fd_non_iso=True)
234+
self.assertEqual(bus.protocol, can.CanProtocol.CAN_FD_NON_ISO)
235+
canlib.canSetBusParams.assert_called_once_with(0, 500_000, 68, 11, 10, 1, 0)
236+
canlib.canSetBusParamsFd.assert_called_once_with(0, 2_000_000, 10, 9, 8)
237+
canlib.canOpenChannel.assert_called_with(
238+
0, constants.canOPEN_CAN_FD_NONISO | constants.canOPEN_ACCEPT_VIRTUAL
239+
)
213240

214241
def test_canfd_nondefault_data_bitrate(self):
215242
canlib.canSetBusParams.reset_mock()

0 commit comments

Comments
 (0)