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 vianetdev_register().include/nuttx/can.h. CAN & CAN FD frame data structures and dlc to len sizeuint8_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 callingnetdev_register().Include/nuttx/net/can.h. contains lookup tables for CAN dlc to CAN FD len sizes namedInitialization 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 driverIn 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)functioninclude/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.cAn example of the txpoll function can be found in
arch/arm/src/s32k1xx/s32k1xx_flexcan.cIn your
transmit(struct driver_s *priv)function you check the length ofnet_driver_s.d_lenwhether it matches the size of astruct can_frameorstruct canfd_framethen you cast the content of thenet_driver_s.d_bufpointer 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/directoryHeader File:
include/nuttx/net/can.hMain Modules:
can_conn.c- Connection managementcan_sockif.c- Socket interface implementationcan_sendmsg.c- Message transmissioncan_sendmsg_buffered.c- Message transmission with bufferingcan_recvmsg.c- Message receptioncan_poll.c- Polling supportcan_callback.c- Callback handling
Configuration Options
To enable SocketCAN, configure the following options:
CONFIG_NET_CAN- Enable SocketCAN supportCONFIG_NET_CAN_NOTIFIER- Enable CAN notifier (optional)CONFIG_NET_CAN_NBUFFERS- Number of CAN buffersCONFIG_NET_RECV_BUFSIZE- Receive buffer size
Usage Notes
SocketCAN uses the standard socket programming model:
/* 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