mirror of
https://github.com/micropython/micropython.git
synced 2026-05-03 14:20:12 +02:00
022570445b
API is different to the original machine.CAN proposal, as numerous shortcomings were found during initial implementation. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
615 lines
25 KiB
ReStructuredText
615 lines
25 KiB
ReStructuredText
.. currentmodule:: machine
|
|
.. _machine.CAN:
|
|
|
|
class CAN -- Controller Area Network protocol
|
|
=============================================
|
|
|
|
CAN is a two-wire serial protocol used for reliable real-time message delivery
|
|
between one or more nodes connected to a common bus. CAN 2.0 was standardised in
|
|
ISO-11898, and is now also known as CAN Classic.
|
|
|
|
There is also a newer, backwards compatible, protocol named CAN FD (CAN with
|
|
Flexible Data-Rate). *The machine.CAN driver does not currently support CAN FD
|
|
features, use `pyb.CAN` on stm32 if you need CAN FD*.
|
|
|
|
CAN support requires a controller (often an internal microcontroller
|
|
peripheral), and an external transceiver to level-shift the signals onto the CAN
|
|
bus.
|
|
|
|
The ``machine.CAN`` interface is a *low level basic* CAN messaging interface
|
|
that abstracts a CAN controller as an outgoing priority queue for sending
|
|
messages, an incoming queue for receiving messages, and mechanisms for reporting
|
|
errors.
|
|
|
|
.. note:: The planned ``can`` and ``aiocan`` micropython-lib modules will be the
|
|
recommended way to use CAN with MicroPython.
|
|
|
|
Constructor
|
|
-----------
|
|
|
|
.. class:: CAN(id, *args, **kwargs)
|
|
|
|
Construct a CAN controller object of the given id:
|
|
|
|
- ``id`` identifies a particular CAN controller object; it is board and port specific.
|
|
- All other arguments are passed to :func:`CAN.init`. At least one argument (``bitrate``)
|
|
must be provided.
|
|
|
|
Future versions of this class may also accept port-specific keyword arguments
|
|
here which configure the hardware. Currently no such keyword arguments are
|
|
implemented.
|
|
|
|
Example
|
|
^^^^^^^
|
|
|
|
Construct and initialise CAN controller 1 with bitrate 500kbps::
|
|
|
|
from machine import CAN
|
|
can = CAN(1, 500_000)
|
|
|
|
.. Add a table of port-specific keyword arguments here, once they exist
|
|
|
|
Methods
|
|
-------
|
|
|
|
.. method:: CAN.init(bitrate, mode=CAN.MODE_NORMAL, sample_point=75, sjw=1, tseg1=None, tseg2=None)
|
|
|
|
Initialise the CAN bus with the given parameters:
|
|
|
|
- *bitrate* is the desired bus bit rate in bits per second.
|
|
- *mode* is one of the values shown under `can-modes`, indicating the
|
|
desired mode of operation. The default is "normal" operation on the bus.
|
|
|
|
The next parameters are optional and relate to CAN bit timings. In most cases
|
|
you can leave these parameters set to the default values:
|
|
|
|
- *sample_point* is an integer percentage of the data bit time. It
|
|
specifies the position of the bit sample with respect to the whole nominal
|
|
bit time. The CAN driver will calculate parameters accordingly. This
|
|
parameter is ignored if *tseg1* and *tseg2* are set.
|
|
- *sjw* is the resynchronisation jump width in units of time quanta for
|
|
nominal bits; it can be a value between 1 and 4 inclusive for classic CAN.
|
|
- *tseg1* defines the location of the sample point in units of time quanta
|
|
for nominal bits; it can be a value between 1 and 16 inclusive for classic
|
|
CAN. This is the sum of the ``Prop_Seg`` and ``Phase_Seg1`` phases as
|
|
defined in the ISO-11898 standard. If this value is set then *tseg2*
|
|
must also be set and *sample_point* is ignored.
|
|
- *tseg2* defines the location of the transmit point in units of the time
|
|
quanta for nominal bits; it can be a value between 1 and 8 inclusive for
|
|
classic CAN. This corresponds to ``Phase_Seg2`` in the ISO-11898 standard.
|
|
If this value is set then *tseg1* must also be set.
|
|
|
|
If these arguments are specified then the CAN controller is configured
|
|
correctly for the desired *bitrate* and the specified total number of time
|
|
quanta per bit. The *tseg1* and *tseg2* values override the
|
|
*sample_point* argument if all of these are supplied.
|
|
|
|
.. note:: Individual controller hardware may have additional restrictions on
|
|
valid values for these parameters, and will raise a ``ValueError``
|
|
if a given value is not supported.
|
|
|
|
.. note:: Specific controller hardware may accept additional optional
|
|
keyword parameters for hardware-specific features such as oversampling.
|
|
|
|
.. method:: CAN.set_filters(filters)
|
|
|
|
Set receive filters in the CAN controller. *filters* can be:
|
|
|
|
- ``None`` to accept all incoming messages, or
|
|
- ``[]`` or ``()`` to disable all message receiving, or
|
|
- An iterable of one or more items defining the filter criteria. Each item
|
|
should be a tuple or list with three elements:
|
|
|
|
- ``identifier`` is a CAN identifier (int).
|
|
- ``bit_mask`` is a bit mask for bits in the CAN identifier field (int).
|
|
- ``flags`` is an integer with zero or more of the bits defined in
|
|
`can-flags` set. This specifies properties that the incoming message needs
|
|
to match. Not all controllers support filtering on all flags, a
|
|
``ValueError`` is raised if an unsupported flag is requested.
|
|
|
|
Incoming messages are accepted if the bits masked in ``bit_mask`` match between
|
|
the message identifier and the filter ``identifier`` value, and flags set in the
|
|
filter match the incoming message.
|
|
|
|
If the `CAN.FLAG_EXT_ID` bit is set in flags, the filter matches Extended
|
|
CAN IDs only. If the `CAN.FLAG_EXT_ID` bit is not set, the filter matches
|
|
Standard CAN IDs only.
|
|
|
|
All filters are ORed together in the controller. Passing an empty list or
|
|
tuple for the filters argument means that no messages will be received.
|
|
|
|
Some CAN controllers require each filter to be associated with only one
|
|
receive FIFO. In these cases, the filter items in the argument are allocated
|
|
round-robin to the available FIFOs. This driver does not distinguish between
|
|
FIFOs in the receive IRQ.
|
|
|
|
.. note:: If the caller passes an iterable with more items than
|
|
:data:`CAN.FILTERS_MAX`, ``ValueError`` will be raised.
|
|
|
|
.. note:: If either the ``identifier`` or the ``bit_mask`` is out of range
|
|
for the specified ID type, a ``ValueError`` with reason "invalid id"
|
|
will be raised.
|
|
|
|
Examples
|
|
^^^^^^^^
|
|
|
|
Receive all incoming messages::
|
|
|
|
can.set_filters(None)
|
|
|
|
Receive messages with Standard ID values 0x301 and 0x700 only::
|
|
|
|
can.set_filters(((0x301, 0x7FF, 0),
|
|
(0x700, 0x7FF, 0)))
|
|
|
|
Receive messages with Standard ID values in range 0x300-0x3FF, and Extended
|
|
ID value 0x50700 only::
|
|
|
|
can.set_filters(((0x300, 0x700, 0),
|
|
(0x50700, 0x1FFF_FFFF, CAN.FLAG_EXT_ID)))
|
|
|
|
.. data:: CAN.FILTERS_MAX
|
|
|
|
Constant value that reads the maximum number of supported receive filters
|
|
for this hardware controller.
|
|
|
|
Note that some controllers may have more complex hardware restrictions on the
|
|
number of filters in use (for example, counting Standard and Extended ID
|
|
filters independently.) In these cases `CAN.set_filters` may raise a
|
|
``ValueError`` even when the ``FILTERS_MAX`` limit is not exceeded.
|
|
|
|
.. method:: CAN.send(id, data, flags=0)
|
|
|
|
Copy a new CAN message into the controller's hardware transmit queue to be
|
|
sent onto the bus. The transmit queue is a priority queue sorted on CAN
|
|
identifier priority (lower numeric identifiers have higher priority).
|
|
|
|
- *id* is an integer CAN identifier value.
|
|
- *data* is a bytes object (or similar) containing the CAN message data,
|
|
or describing a Remote Transmission Request (see below).
|
|
- *flags* is an integer with zero or more of the bits defined in
|
|
`can-flags` set, specifying properties of the outgoing CAN message
|
|
(Extended ID, Remote Transmission Request, etc.)
|
|
|
|
If the message is successfully queued for transmit onto the bus, the function
|
|
returns an integer in the range ``0`` to `CAN.TX_QUEUE_LEN` (exclusive). This
|
|
value is the transmit buffer index where the message is queued to send, and
|
|
can be used by the `CAN.cancel_send` function and in `CAN.IRQ_TX` events.
|
|
|
|
If the queue is full then the send will fail and ``None`` is returned.
|
|
|
|
The send can also fail and return ``None`` if the provided *id* value has
|
|
equal priority to an existing message in the transmit queue and the CAN
|
|
controller hardware cannot guarantee that messages with the same ID will be
|
|
sent onto the bus in the same order they were added to the queue. To queue
|
|
the message anyway, pass the value :data:`CAN.FLAG_UNORDERED` flag in
|
|
the *flags* argument. This flag indicates that it's OK to send messages with
|
|
the same CAN ID onto the bus in any order.
|
|
|
|
If the controller is in the "Bus Off" error state or disabled then calling
|
|
this function will raise an ``OSError``.
|
|
|
|
.. note:: This intentionally low-level implementation is designed so the
|
|
caller can establish a software queue of outgoing messages.
|
|
|
|
.. important:: The CAN "transmit queue" is not a FIFO queue, it is priority
|
|
ordered, and although it can hold up to `CAN.TX_QUEUE_LEN`
|
|
items there may be other hardware restrictions on messages
|
|
which can be queued at the same time.
|
|
|
|
Remote Transmission Requests
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If the bit `CAN.FLAG_RTR` is set in the *flags* argument then the controller
|
|
will send a Remote Transmission Request instead of a message. In this case
|
|
the contents of the *data* argument is ignored. The controller will send
|
|
a request where the ``DLC`` length field is equal to the length of the
|
|
*data* argument.
|
|
|
|
Examples
|
|
^^^^^^^^
|
|
|
|
Attempt to send a message with three byte payload ``0a0b0c`` and Standard ID 0x200::
|
|
|
|
can.send(0x200, b"\x0a\x0b\x0c", 0)
|
|
|
|
Attempt to send a message with an empty payload and Extended ID 0x180008.
|
|
Indicate that the controller can send messages with this ID in any order, in
|
|
case other messages are already queued to send with the same ID::
|
|
|
|
can.send(0x180008, b"", can.FLAG_EXT_ID | can.FLAG_UNORDERED)
|
|
|
|
Attempt to send a Remote Transmission Request with length 8 bytes and Standard ID 0x555::
|
|
|
|
can.send(0x555, b" " * 8, can.FLAG_RTR)
|
|
|
|
.. method:: CAN.recv(arg=None)
|
|
|
|
Return a CAN message that has been received by the controller, according to
|
|
filters set by :func:`CAN.set_filters`.
|
|
|
|
This function takes a single optional argument, if provided then it must be a
|
|
list of at least 4 elements where the second element is a `memoryview` object
|
|
that refers to a `bytearray` or similar object that has enough capacity to hold
|
|
any received CAN message (8 bytes for CAN Classic, 64 bytes for CAN FD). The
|
|
provided list will be returned as a successful result, and avoids memory
|
|
allocation inside the function.
|
|
|
|
If no messages have been received by the CAN controller, this function
|
|
returns ``None``.
|
|
|
|
.. note:: `CAN.set_filters` must be called before any messages can be received by
|
|
the controller. To receive all messages, call ``set_filters(None)``.
|
|
|
|
If a message has been received by the CAN controller, this function returns a
|
|
list with 4 elements:
|
|
|
|
- Index 0 is the CAN ID of the received message, as an integer.
|
|
- Index 1 is a memoryview that provides access to the received message data.
|
|
|
|
- If *arg* is not provided then this is a `memoryview` holding the bytes
|
|
which were received. This `memoryview` is backed by a newly allocated
|
|
`bytearray` large enough to hold any received CAN message. This allows
|
|
the result to be safely reused as a future *arg*, to save memory allocations.
|
|
- If *arg* is provided then the provided `memoryview` will be resized to
|
|
hold exactly the bytes which were received. The caller is responsible for
|
|
making sure the backing object for the `memoryview` can hold a CAN
|
|
message of any length.
|
|
|
|
- Index 2 is an integer with zero or more of the bits defined in
|
|
`can-flags` set. It indicates metadata about the received message.
|
|
- Index 3 is an integer with zero or more of the bits defined in
|
|
`can-recv-errors` set. Any non-zero value indicates potential issues when
|
|
receiving CAN messages. These flags are reset inside the controller each
|
|
time this function returns.
|
|
|
|
Remote Transmission Requests
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If a Remote Transmission Request is received then the bit `CAN.FLAG_RTR`
|
|
will be set in Index 2 and the memoryview at Index 1 will contain all
|
|
zeroes, with a length equal to the ``DLC`` field of the received request.
|
|
|
|
Example
|
|
^^^^^^^
|
|
::
|
|
|
|
can.set_filters(None) # receive all
|
|
while True:
|
|
res = can.recv()
|
|
if res:
|
|
can_id, data, flags, errs = res
|
|
print("Received", hex(can_id), data.hex(), hex(flags), hex(errs))
|
|
else:
|
|
time.sleep_ms(1) # not a good pattern, use the irq instead!
|
|
|
|
|
|
.. method:: CAN.irq(handler=None, trigger=0, hard=False)
|
|
|
|
Sets an interrupt *handler* function to be called when one or more of the
|
|
events flagged in *trigger* has occurred.
|
|
|
|
- *handler* is a function to be called when the interrupt event
|
|
triggers. The handler must take exactly one argument which is the
|
|
:class:`CAN` instance.
|
|
|
|
- *trigger* configures the event(s) which can generate an interrupt.
|
|
Possible values are a mask of one or more of the following:
|
|
|
|
- `CAN.IRQ_RX` event occurs after the CAN controller has received
|
|
at least one message into its RX FIFO (meaning that :func:`CAN.recv()`
|
|
will return successfully).
|
|
- `CAN.IRQ_TX` event occurs after the CAN controller has either
|
|
successfully sent a message onto the CAN bus or failed to send a
|
|
message. This trigger has additional requirements for the handler, see
|
|
`machine_can_irq_flags` for details.
|
|
- `CAN.IRQ_STATE` event occurs when the CAN controller has transitioned
|
|
into a more severe error state. Call :func:`CAN.state()` to get the
|
|
updated state.
|
|
|
|
- *hard* if True, a hard interrupt is used. This reduces the delay between
|
|
the CAN controller event and the handler being called. Hard interrupt
|
|
handlers may not allocate memory; see :ref:`isr_rules`.
|
|
|
|
Returns an irq object. If called with no arguments then a previously-configured
|
|
irq object is returned.
|
|
|
|
See `machine_can_irq_flags` for an example.
|
|
|
|
.. method:: CAN.cancel_send(index)
|
|
|
|
Request the CAN controller to cancel sending a message onto the bus.
|
|
|
|
Argument *index* identifies a single transmit buffer. It should be an
|
|
integer in the range ``0`` to ``CAN.TX_QUEUE_LEN`` (exclusive). Generally
|
|
this will be a value previously returned by :func:`CAN.send()`.
|
|
|
|
The result is ``True`` if a message was pending transmission in this buffer
|
|
and transmission was cancelled.
|
|
|
|
The result is ``False`` otherwise (either no message was pending transmission
|
|
in this buffer, or transmission succeeded already).
|
|
|
|
The IRQ event `CAN.IRQ_TX` should be used to determine if a message
|
|
was definitely sent or not, but note there are potential race conditions if a
|
|
transmission is cancelled and then the same buffer is used to send another
|
|
message (especially if the CAN controller IRQ is not "hard").
|
|
|
|
.. method:: CAN.state()
|
|
|
|
Returns an integer value indicating the current state of the controller.
|
|
The value will be one of the values defined in `can-states`.
|
|
|
|
Lower severity error states may automatically clear if the bus recovers, but
|
|
the `CAN.STATE_BUS_OFF` state can only be recovered by calling
|
|
:func:`CAN.restart()`.
|
|
|
|
.. method:: CAN.get_counters(list=None /)
|
|
|
|
Returns controller's error counter values. The result is a list of eight
|
|
values. If the optional *list* parameter is specified then the provided
|
|
list object is updated and returned as the result, to avoid an allocation.
|
|
|
|
The list items are:
|
|
|
|
- TEC (Transmit Error Counter) value
|
|
- REC (Receive Error Counter) value
|
|
- Number of times the controller entered the Warning state from the Active state.
|
|
- Number of times the controller entered the Error Passive state from the Warning state.
|
|
- Number of times the controller entered the Bus Off state from the Error Passive state.
|
|
- Total number of pending TX messages in the hardware queue.
|
|
- Total number of pending RX messages in the hardware queue.
|
|
- Number of times an RX overrun occurred.
|
|
|
|
.. note:: Depending on the controller, these values may overflow back to 0 after
|
|
a certain value.
|
|
|
|
.. note:: If a controller doesn't support a particular counter, it will return
|
|
``None`` for that list element.
|
|
|
|
.. method:: CAN.get_timings(list=None /)
|
|
|
|
Returns a list of elements indicating the current timings configured in the
|
|
CAN controller. This can be used to verify timings for debugging purposes.
|
|
The result is a list of six values. If the optional *list* parameter is
|
|
specified then the provided list object is updated and returned as the
|
|
result, to avoid an allocation.
|
|
|
|
The list items are:
|
|
|
|
- Exact bitrate used by the controller. May vary from *bitrate* argument
|
|
passed to :func:`CAN.init()` due to quantisation to meet hardware
|
|
constraints.
|
|
- Resynchronisation jump width (SJW) in units of time quanta for nominal
|
|
bits. Has the same meaning as the *sjw* parameter of :func:`CAN.init()`.
|
|
- Location of the sample point in units of time quanta for nominal bits. Has
|
|
the same meaning as the *tseg1* parameter of :func:`CAN.init()`.
|
|
- Location of the transmit point in units of time quanta for nominal bits.
|
|
Has the same meaning as the *tseg2* parameter of :func:`CAN.init()`.
|
|
- CAN FD timing information. ``None`` for controllers which don't support CAN
|
|
FD, or if CAN FD is not initialised. Otherwise, a nested list of four
|
|
elements corresponding to the items above but applicable to the CAN FD BRS
|
|
feature.
|
|
- Optional controller-specific timing information. Depending on the
|
|
controller this will either be ``None`` if controller doesn't report any,
|
|
or it will be a constant length list whose elements are specific to a
|
|
particular hardware controller.
|
|
|
|
.. note:: If :func:`CAN.init()` has not been called then this function
|
|
still returns a result, but the result depends on the controller
|
|
internals and may not be accurate.
|
|
|
|
.. method:: CAN.restart()
|
|
|
|
Causes the controller to exit `STATE_BUS_OFF` without clearing any other
|
|
internal state. Also clears some of the error counters (always the number
|
|
of times each error state has been entered, possibly TEC and REC depending
|
|
on the controller.)
|
|
|
|
Calling this function also cancels any messages waiting to be sent. No
|
|
`IRQ_TX` interrupts are delivered for these messages.
|
|
|
|
Note that this function may or may not cause the controller to exit the
|
|
"Error Passive" state, depending whether the controller hardware zeroes
|
|
TEC and REC or not.
|
|
|
|
.. method:: CAN.deinit()
|
|
|
|
De-initialises a previously active CAN instance. All pending messages
|
|
(transmit and receive) are dropped and the controller stops interacting on
|
|
the bus. To use this instance again, call :func:`CAN.init()`.
|
|
|
|
No `IRQ_TX` or `IRQ_RX` interrupts are called in response to calling this
|
|
function.
|
|
|
|
See also :func:`CAN.restart()`.
|
|
|
|
Constants
|
|
---------
|
|
|
|
.. data:: CAN.TX_QUEUE_LEN
|
|
|
|
Maximum number of CAN messages which can be queued in the outgoing hardware
|
|
message queue of the controller. The "transmit buffer indexes" used by
|
|
:func:`CAN.send()`, :func:`CAN.cancel_send()` and `machine_can_irq_flags`
|
|
will be in this range.
|
|
|
|
.. _can-modes:
|
|
|
|
Modes
|
|
^^^^^
|
|
|
|
These values represent controller modes of operation, as passed to `CAN.init()`. Not all controllers may support all modes.
|
|
|
|
Changing the mode of a running controller requires calling `CAN.deinit()` and then calling `CAN.init()` again with the new mode.
|
|
|
|
.. data:: CAN.MODE_NORMAL
|
|
|
|
The controller is active as a standard CAN network node (will acknowledge
|
|
valid messages and may transmit errors depending on its current `State
|
|
<can-states>`).
|
|
|
|
.. data:: CAN.MODE_SLEEP
|
|
|
|
CAN controller is asleep in a low power mode. Depending on the controller,
|
|
this may support waking the controller and transitioning to `CAN.MODE_NORMAL`
|
|
if CAN traffic is received.
|
|
|
|
.. data:: CAN.MODE_LOOPBACK
|
|
|
|
A testing mode. The CAN controller is still connected to the external bus,
|
|
but will also receive its own transmitted messages and ignore any ACK errors.
|
|
|
|
.. data:: CAN.MODE_SILENT
|
|
|
|
CAN controller receives messages but does not interact with the CAN bus
|
|
(including sending ACKs, errors, etc.)
|
|
|
|
.. data:: CAN.MODE_SILENT_LOOPBACK
|
|
|
|
A testing mode that does not require a CAN transceiver to be connected at
|
|
all. The CAN controller receives its own transmitted messages without
|
|
interacting with the CAN bus at all. The CAN TX and RX pins remain idle.
|
|
|
|
.. _can-states:
|
|
|
|
States
|
|
^^^^^^
|
|
|
|
These values are returned by :func:`CAN.state()` and reflect the error state of the CAN controller:
|
|
|
|
.. data:: CAN.STATE_STOPPED
|
|
|
|
The controller has not been initialised.
|
|
|
|
.. data:: CAN.STATE_ACTIVE
|
|
|
|
The controller is active and ``TEC`` and ``REC`` error counters are both below the
|
|
warning threshold of 96. See :func:`CAN.get_counters()`.
|
|
|
|
.. data:: CAN.STATE_WARNING
|
|
|
|
The controller is active but at last one of the ``TEC`` and ``REC`` error counters
|
|
are between 96 and 127. See :func:`CAN.get_counters()`.
|
|
|
|
.. data:: CAN.STATE_PASSIVE
|
|
|
|
The controller is in the "Error Passive" state meaning it no longer transmits active
|
|
errors to the bus, but it is otherwise functional. This state is entered when at
|
|
least one of the ``TEC`` and ``REC`` error counters is 128 or greater, but
|
|
``TEC`` is less than 255. See :func:`CAN.get_counters()`.
|
|
|
|
.. data:: CAN.STATE_BUS_OFF
|
|
|
|
The controller is in the Bus-Off state, meaning ``TEC`` error counter is
|
|
greater than 255. The CAN controller will not interact with the bus in this
|
|
state, and needs to be restarted via :func:`CAN.restart()` to continue.
|
|
|
|
.. _can-flags:
|
|
|
|
Message Flags
|
|
^^^^^^^^^^^^^
|
|
|
|
These values represent metadata about a CAN message. Functions
|
|
:func:`CAN.send()`, :func:`CAN.recv()`, and :func:`CAN.set_filters()` either
|
|
accept or return an integer value made up of zero or more of these flags bitwise
|
|
ORed together.
|
|
|
|
.. data:: CAN.FLAG_RTR
|
|
|
|
Indicates a message is a remote transmission request.
|
|
|
|
.. data:: CAN.FLAG_EXT_ID
|
|
|
|
If set, indicates a Message identifier is Extended (29-bit). If not set,
|
|
indicates a message identifier is Standard (11-bit).
|
|
|
|
.. data:: CAN.FLAG_UNORDERED
|
|
|
|
If set in the ``flags`` argument of :func:`CAN.send`, indicates that it's
|
|
OK if messages with the same CAN ID are sent in any order onto the bus.
|
|
|
|
Otherwise trying to queue multiple messages with the same ID may result in
|
|
:func:`CAN.send` failing if the controller hardware can't enforce ordering.
|
|
|
|
This flag is never set on received messages, and is ignored by
|
|
`CAN.set_filters()`.
|
|
|
|
.. _can-recv-errors:
|
|
|
|
Receive Error Flags
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
The result of :func:`CAN.recv()` includes an integer value made up of zero or
|
|
more of these flags bitwise ORed together. If set, these flags indicate
|
|
potential general issues with receiving CAN messages.
|
|
|
|
.. data:: CAN.RECV_ERR_FULL
|
|
|
|
The hardware FIFO where this message was received is full, and additional incoming messages may be lost.
|
|
|
|
.. data:: CAN.RECV_ERR_OVERRUN
|
|
|
|
The hardware FIFO where this message was received is full, and one or more incoming messages has been lost.
|
|
|
|
IRQ values
|
|
^^^^^^^^^^
|
|
|
|
.. data:: CAN.IRQ_RX
|
|
CAN.IRQ_TX
|
|
CAN.IRQ_STATE
|
|
|
|
IRQ event triggers. Used with :func:`CAN.irq()` and `machine_can_irq_flags`.
|
|
|
|
.. data:: CAN.IRQ_TX_FAILED
|
|
CAN.IRQ_TX_IDX_SHIFT
|
|
CAN.IRQ_TX_IDX_MASK
|
|
|
|
Additional IRQ event flags for `CAN.IRQ_TX`. See `machine_can_irq_flags`.
|
|
|
|
.. _machine_can_irq_flags:
|
|
|
|
IRQ flags
|
|
---------
|
|
|
|
Calling :func:`CAN.irq()` registers an interrupt handler with one or more of the
|
|
triggers `CAN.IRQ_RX`, `CAN.IRQ_TX` and `CAN.IRQ_STATE`.
|
|
|
|
The function returns an IRQ object, and calling the ``flags()`` function on this
|
|
object returns an integer indicating which trigger event(s) triggered the
|
|
interrupt. A CAN IRQ handler should call the ``flags()`` function repeatedly
|
|
until it returns ``0``.
|
|
|
|
When the ``flags()`` function returns with `CAN.IRQ_TX` bit set, the
|
|
handler can also check the following flag bits in the result for additional
|
|
information about the TX event:
|
|
|
|
* ``CAN.IRQ_TX_FAILED`` bit is set if the transmit failed. Usually this will
|
|
only happen if :func:`CAN.cancel_send()` was called, although it may also
|
|
happen if the controller enters an error state.
|
|
* ``CAN.IRQ_TX_MASK << CAN.IRQ_TX_SHIFT`` is a bitmasked region of the flags
|
|
value that holds the index of the transmit buffer which generated the event.
|
|
This will be an integer in the range ``0`` to `CAN.TX_QUEUE_LEN` (exclusive),
|
|
and will match the result of a previous call to `CAN.send()`.
|
|
|
|
IRQ_TX Example
|
|
^^^^^^^^^^^^^^
|
|
::
|
|
|
|
from machine import CAN
|
|
|
|
def irq_send(can):
|
|
while flags := can.irq().flags():
|
|
if flags & can.IRQ_TX:
|
|
idx = (flags >> can.IRQ_TX_IDX_SHIFT) & can.IRQ_TX_IDX_MASK
|
|
success = not (flags & can.IRQ_TX_FAILED)
|
|
print("irq_send", idx, success)
|
|
|
|
can = CAN(1, 500_000)
|
|
can.irq(irq_send, trigger=can.IRQ_TX, hard=True)
|
|
|
|
.. important:: If the `CAN.IRQ_TX` trigger is set then the handler **must**
|
|
call ``flags()`` repeatedly until it returns ``0``, as shown in
|
|
this example. Otherwise, CAN interrupts may not be correctly
|
|
re-enabled.
|