nuttx/Documentation/components/net/socketcan.rst

149 lines
5.2 KiB
ReStructuredText
Raw Normal View History

=========
SocketCAN
=========
SocketCAN Device Drivers
========================
- ``include/nuttx/net/netdev.h``. All structures and APIs
needed to work with drivers are provided in this header file.
The structure struct net_driver_s defines the interface and is
passed to the network via ``netdev_register()``.
- ``include/nuttx/can.h``. CAN & CAN FD frame data structures and dlc to len size
.. code-block:: c
uint8_t can_bytes2dlc(uint8_t nbytes);
uint8_t can_dlc2bytes(uint8_t dlc);
- ``int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)'``.
Each driver registers itself by calling ``netdev_register()``.
- ``Include/nuttx/net/can.h``. contains lookup tables for CAN
dlc to CAN FD len sizes named
- **Initialization sequence is as follows**.
#. ``xxx_netinitialize(void)`` is called on startup of NuttX in this
function you call your own init function to initialize your
CAN driver
#. In your own init function you create the net_driver_s
structure set required init values and register the required
callbacks for SocketCAN
#. Then you ensure that the CAN interface is in down mode
(usually done by calling the d_ifdown function)
#. Register the net_driver_s using netdev_register
- **Receive sequence is as follows**.
#. Device generates interrupt
#. Process this interrupt in your interrupt handler
#. When a new CAN frame has been received you process this frame
#. When the CAN frame is a normal CAN frame you allocate the
can_frame struct, when it's a CAN FD frame you allocate a
canfd_frame struct (note you can of course preallocate and
just use the pointer).
#. Copy the frame from the driver to the struct you've
allocated in the previous step.
#. Point the net_driver_s d_buf pointer to the allocated can_frame
#. Call the ``can_input(FAR struct net_driver_s *dev)``
function ``include/nuttx/net/can.h``
- **Transmit sequence is as follows**.
#. Socket layer executes d_txavail callback
#. An example of the txavail function can be found in
``arch/arm/src/s32k1xx/s32k1xx_flexcan.c``
#. An example of the txpoll function can be found in
``arch/arm/src/s32k1xx/s32k1xx_flexcan.c``
#. In your ``transmit(struct driver_s *priv)`` function you
check the length of ``net_driver_s.d_len`` whether it
matches the size of a ``struct can_frame`` or
``struct canfd_frame`` then you cast the content of the
``net_driver_s.d_buf`` pointer to the correct CAN frame struct
SocketCAN protocol stack
========================
SocketCAN is a CAN protocol stack implementation based on the BSD socket API,
providing a more standardized and flexible CAN communication interface.
SocketCAN uses the network protocol stack framework, allowing applications
to use standard socket system calls (such as ``socket()``, ``bind()``,
``send()``, ``recv()``, etc.) for CAN communication.
Architecture
------------
The SocketCAN implementation follows the standard network layer hierarchy:
#. **Application Layer Interface**: Uses standard socket API
(AF_CAN address family)
#. **Protocol Layer**: CAN protocol processing (located in ``net/can/``)
#. **Device Layer**: CAN network device drivers
File Locations
--------------
Files supporting SocketCAN can be found in the following locations:
- **Protocol Implementation**: The SocketCAN protocol stack is located in
the ``net/can/`` directory
- **Header File**: ``include/nuttx/net/can.h``
- **Main Modules**:
- ``can_conn.c`` - Connection management
- ``can_sockif.c`` - Socket interface implementation
- ``can_sendmsg.c`` - Message transmission
- ``can_sendmsg_buffered.c`` - Message transmission with buffering
- ``can_recvmsg.c`` - Message reception
- ``can_poll.c`` - Polling support
- ``can_callback.c`` - Callback handling
Configuration Options
---------------------
To enable SocketCAN, configure the following options:
- ``CONFIG_NET_CAN`` - Enable SocketCAN support
- ``CONFIG_NET_CAN_NOTIFIER`` - Enable CAN notifier (optional)
- ``CONFIG_NET_CAN_NBUFFERS`` - Number of CAN buffers
- ``CONFIG_NET_RECV_BUFSIZE`` - Receive buffer size
Usage Notes
-----------
SocketCAN uses the standard socket programming model:
.. code-block:: c
/* Create CAN socket */
int sock = socket(AF_CAN, SOCK_RAW, CAN_RAW);
/* Bind to CAN interface */
struct sockaddr_can addr;
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex("can0");
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
/* Send CAN frame */
struct can_frame frame;
frame.can_id = 0x123;
frame.can_dlc = 8;
/* Fill data */
send(sock, &frame, sizeof(frame), 0);
/* Receive CAN frame */
recv(sock, &frame, sizeof(frame), 0);
Features
--------
- **Standard Socket API**: Uses familiar socket programming interface
- **Filtering Support**: Set CAN ID filters via socket options
- **Non-blocking I/O**: Supports non-blocking mode and polling
- **Multiple Connections**: Supports multiple sockets accessing the same CAN bus simultaneously
- **Read Buffering**: Supports data read buffering to prevent data loss
- **CAN FD Support**: Supports CAN FD frames if enabled in configuration
- **Extensible**: Easy to extend for additional CAN protocols