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 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 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.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