From 22a71ffc177718d460993626ce17122ba1d03f58 Mon Sep 17 00:00:00 2001 From: Lukas Lendvorsky Date: Thu, 11 Dec 2025 19:46:47 +0100 Subject: [PATCH 1/3] Add option to disable bit rate switching for socket can When running in CAN-FD mode, but with same nominal and data baudrate, BRS bit has to remain at zero. That indicates that there is no bitrate switch happening for data and data is transmitted at same speed. --- pycyphal/application/_transport_factory.py | 3 ++- .../transport/can/media/socketcan/_socketcan.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pycyphal/application/_transport_factory.py b/pycyphal/application/_transport_factory.py index 014f6093..b5a3a7ea 100644 --- a/pycyphal/application/_transport_factory.py +++ b/pycyphal/application/_transport_factory.py @@ -283,6 +283,7 @@ def init(name: str, default: RelaxedValue) -> ValueProxy: iface_list = str(init("iface", "")).split() mtu = int(init("mtu", Natural16([64]))) br_arb, br_data = init("bitrate", Natural32([1_000_000, 4_000_000])).ints + disable_brs = bool(init("disable_brs", br_arb == br_data)) if iface_list: from pycyphal.transport.can import CANTransport @@ -292,7 +293,7 @@ def init(name: str, default: RelaxedValue) -> ValueProxy: if iface.lower().startswith("socketcan:"): from pycyphal.transport.can.media.socketcan import SocketCANMedia - media = SocketCANMedia(iface.split(":", 1)[-1], mtu=mtu) + media = SocketCANMedia(iface.split(":", 1)[-1], mtu=mtu, disable_brs=disable_brs) elif iface.lower().startswith("candump:"): from pycyphal.transport.can.media.candump import CandumpMedia diff --git a/pycyphal/transport/can/media/socketcan/_socketcan.py b/pycyphal/transport/can/media/socketcan/_socketcan.py index 8b81ac4d..a9b2a928 100644 --- a/pycyphal/transport/can/media/socketcan/_socketcan.py +++ b/pycyphal/transport/can/media/socketcan/_socketcan.py @@ -41,7 +41,13 @@ class SocketCANMedia(Media): SocketCAN documentation: https://www.kernel.org/doc/Documentation/networking/can.txt """ - def __init__(self, iface_name: str, mtu: int, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def __init__( + self, + iface_name: str, + mtu: int, + disable_brs: bool = False, + loop: typing.Optional[asyncio.AbstractEventLoop] = None, + ) -> None: """ CAN Classic/FD is selected automatically based on the MTU. It is not possible to use CAN FD with MTU of 8 bytes. @@ -50,6 +56,9 @@ def __init__(self, iface_name: str, mtu: int, loop: typing.Optional[asyncio.Abst :param mtu: The maximum data field size in bytes. CAN FD is used if this value > 8, Classic CAN otherwise. This value must belong to Media.VALID_MTU_SET. + :param disable_brs: When true, will disable bitrate switching for CAN FD frames. Meaning that the data bitrate + will be the same as the nominal bitrate. + :param loop: Deprecated. """ # This can't be made a class attribute because these errnos are only available on GNU/Linux. @@ -68,6 +77,8 @@ def __init__(self, iface_name: str, mtu: int, loop: typing.Optional[asyncio.Abst self._mtu = int(mtu) if self._mtu not in self.VALID_MTU_SET: raise ValueError(f"Invalid MTU: {self._mtu} not in {self.VALID_MTU_SET}") + self._disable_brs: bool = disable_brs + if loop: warnings.warn("The loop argument is deprecated", DeprecationWarning) @@ -260,7 +271,7 @@ def _read_frame(self, ts_mono_ns: int) -> typing.Tuple[Timestamp, Envelope]: return timestamp, Envelope(out, loopback=loopback) def _compile_native_frame(self, source: DataFrame) -> bytes: - flags = _CANFD_BRS if self._is_fd else 0 + flags = _CANFD_BRS if (self._is_fd and not self._disable_brs) else 0 ident = source.identifier | (_CAN_EFF_FLAG if source.format == FrameFormat.EXTENDED else 0) header = _FRAME_HEADER_STRUCT.pack(ident, len(source.data), flags) out = header + source.data.ljust(self._native_frame_data_capacity, b"\x00") From de1add0e1fbd7ea80f9b7abf9a0683325c973961 Mon Sep 17 00:00:00 2001 From: Lukas Lendvorsky Date: Mon, 22 Dec 2025 12:45:22 +0100 Subject: [PATCH 2/3] Bump version and add changelog entry --- CHANGELOG.rst | 5 +++++ pycyphal/_version.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bfde77b0..c6ac0f28 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,11 @@ Changelog ========= +v1.25 +----- + +- SocketCAN: Add option to disable bit-rate switching (BRS bit) for FD-CAN with uavcan.udp.disable_brs. (`#373 `_) + v1.24 ----- diff --git a/pycyphal/_version.py b/pycyphal/_version.py index b1b8e08c..4839ffd6 100644 --- a/pycyphal/_version.py +++ b/pycyphal/_version.py @@ -1 +1 @@ -__version__ = "1.24.5" +__version__ = "1.25.1" From 996dfc067876f7d718e697ece37d151e3b4a6d57 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Tue, 30 Dec 2025 12:40:06 +0200 Subject: [PATCH 3/3] Update _version.py --- pycyphal/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycyphal/_version.py b/pycyphal/_version.py index 4839ffd6..d1067bcb 100644 --- a/pycyphal/_version.py +++ b/pycyphal/_version.py @@ -1 +1 @@ -__version__ = "1.25.1" +__version__ = "1.25.0"