======================== 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. - ``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 .. code-block:: c extern const uint8_t can_dlc_to_len[16]; extern const uint8_t len_to_can_dlc[65]; - **Initialization sequence is as follows**. #. up_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