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- extern const uint8_t can_dlc_to_len[16]; extern const uint8_t len_to_can_dlc[65]; 
- 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_lenwhether it matches the size of a- struct can_frameor- struct canfd_framethen you cast the content of the- net_driver_s.d_bufpointer to the correct CAN frame struct