On Wed, 2017-07-19 at 16:55 +0300, Jukka Rissanen wrote:
Hi Erwin,
On Wed, 2017-07-19 at 14:39 +0200, Erwin Rol wrote:
Hallo all,
I am working on a CAN driver for STM32F4 and am having a few
conceptual
problems. How to generalize the interface to hardware that can be
very
different. For example the hardware-msg-filtering, two selectable
receive FIFO's, the second CAN port shares hardware with the first
port,
etc. are rather unique to the STM32 hardware. Other CAN controllers
have other features.
This is not just a CAN-driver problem, a same problem is setting the
multicast-filters of Ethernet hardware, they also come in a lot of
different flavors.
So how do I offer a Zephyr application a generic CAN interface (or
device interface for that matter)? If I make is
lowest-common-denominator generic (for CAN just sending and receiving
CAN frames) a lot of advanced feature will be lost that might really
make a difference between a working and non-working application (for
example hardware filtering that prevents CPU/IRQ overload).
We could follow the same idea as IEEE 802.15.4 radio API is doing. So
each CAN hw driver would need to provide a set of function pointers to
do various CAN operations. See include/net/ieee802154_radio.h for
details.
For doing various management operations, we have the net_mgmt interface
that should be used. See include/net/net_mgmt.h for details.
OK I'll look into that to see how it fits my needs (and if it isn't to
much more work how it would fit other ppl's needs).
For application that wants to send/receive actual CAN data, do we need
to create a new API for that, or could we extend the current
net_context API to support CAN interfaces? So similar way as what Linux
is doing things with SocketCAN.
I am not sure if that is the right way to go for resource constraint
systems like Zephyr.
First CAN frames are really small, they have maximum 8 data bytes, 4 len
bits, 29 ID bits and some flag bits. So a CAN frame struct would be
something like;
struct can_frame {
u32 id;
u8 data[8];
u8 len_flags;
}
And even CAN-FD has only 64 data bytes, so still smaller than a useful
net_pkt buffer size (default 128 bytes I believe). So all stuff to chain
packets/frames is useless for CAN, and just causes memory overhead.
Secondly there can be a lot of frames per second, CAN is a broadcast
bus, and everybody receives everything (unless they have hardware to
filter out certain frames). And with 1Mbit/s you could have almost 10k
frames per second.
Keeping those two things in mind I would want to keep the handling
overhead as small as possible.
But the low level CAN driver is just one part, mostly there will be
something like CANopen (which isn't as open as the name suggests :/)
running on top of it. Maybe CANsockets can also be a layer on top of the
low level CAN driver? I have not yet looked at the net_pkt buffers in
detail, but maybe the CAN-frame buffer could just be the data part, and
so one could do a zero-copy transformation from a CAN-frame into a
network packet ?
- Erwin