Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions can/interfaces/socketcan/socketcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,9 @@ def __init__(
self.task_id = task_id
self._tx_setup(self.messages)

def _tx_setup(self, messages: Sequence[Message]) -> None:
def _tx_setup(
self, messages: Sequence[Message], raise_if_task_exists: bool = True
) -> None:
# Create a low level packed frame to pass to the kernel
body = bytearray()
self.flags = CAN_FD_FRAME if messages[0].is_fd else 0
Expand All @@ -363,7 +365,8 @@ def _tx_setup(self, messages: Sequence[Message]) -> None:
ival1 = 0.0
ival2 = self.period

self._check_bcm_task()
if raise_if_task_exists:
self._check_bcm_task()

header = build_bcm_transmit_header(
self.task_id, count, ival1, ival2, self.flags, nframes=len(messages)
Expand All @@ -375,7 +378,7 @@ def _tx_setup(self, messages: Sequence[Message]) -> None:

def _check_bcm_task(self) -> None:
# Do a TX_READ on a task ID, and check if we get EINVAL. If so,
# then we are referring to a CAN message with the existing ID
# then we are referring to a CAN message with an existing ID
check_header = build_bcm_header(
opcode=CAN_BCM_TX_READ,
flags=0,
Expand All @@ -387,12 +390,19 @@ def _check_bcm_task(self) -> None:
can_id=self.task_id,
nframes=0,
)
log.debug(
f"Reading properties of (cyclic) transmission task id={self.task_id}",
)
try:
self.bcm_socket.send(check_header)
except OSError as error:
if error.errno != errno.EINVAL:
raise can.CanOperationError("failed to check", error.errno) from error
else:
log.debug("Invalid argument - transmission task not known to kernel")
else:
# No exception raised - transmission task with this ID exists in kernel.
# Existence of an existing transmission task might not be a problem!
raise can.CanOperationError(
f"A periodic task for task ID {self.task_id} is already in progress "
"by the SocketCAN Linux layer"
Expand Down Expand Up @@ -438,15 +448,15 @@ def modify_data(self, messages: Union[Sequence[Message], Message]) -> None:
send_bcm(self.bcm_socket, header + body)

def start(self) -> None:
"""Start a periodic task by sending TX_SETUP message to Linux kernel.
"""Restart a periodic task by sending TX_SETUP message to Linux kernel.

It verifies presence of the particular BCM task through sending TX_READ
message to Linux kernel prior to scheduling.

:raises ValueError:
If the task referenced by ``task_id`` is already running.
"""
self._tx_setup(self.messages)
self._tx_setup(self.messages, raise_if_task_exists=False)


class MultiRateCyclicSendTask(CyclicSendTask):
Expand Down