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.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 namedextern const uint8_t g_can_dlc_to_len[16]; extern const uint8_t g_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)
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.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 ofnet_driver_s.d_len
whether it matches the size of astruct can_frame
orstruct canfd_frame
then you cast the content of thenet_driver_s.d_buf
pointer to the correct CAN frame struct