 Good afternoon everybody. Thank you for being here. Today I'm going to present an overview of canned protocol, canned subsystem in Yazzafer. Myself, Navin Shankar, Nalambati Velingiri, I'm working as an embedded software engineer at next big thing, AG. So I'm currently working and living in Berlin. So these are the topics I'm going to cover today. Like what is canned, futures and application, canned bus architecture, canned subsystem in Zazfer, sample application and user space tools like canned utility to debug the software. And what is canned? Can't stand for controller area network. So it was initially developed by Robert Bosch and now it has become an international standard ISO 11898 for robust and reliable communication between electronic device. It is a multi-master serial and broadcast bus, meaning any node can send and receive the data to any other node in the network and all the nodes connected in the network can receive the message. And it is a message, canned is a message based protocol, meaning it transmits message in form of frames. So the frame consists of frame header, payload and frame tailor and can operates at different data rate from 125 kilobits per second to one mahogany bits per second, depend on user application, we can configure it to 125 or 250 or 500 kilobits per second. So canned futures. It's a multi-master protocol and multi-node architecture. It's it provides a reliable message transmission, so canned utilizes priority based arbitration, meaning message ID with lower ID, lower identifier value can pre-match the message with higher identifier value on the bus. And it has a built-in future called error direction and error correction. It is low cost and easy to implement. It uses twisted path cable to transmit the differential signal to nodes applications. So because of it, robotness, robustness, real-time capability and reliability can is used in various fields like automotive domain, aerospace and aviation, industrial automation, building automation and medical device. This is how a signaling looks like. So basically it consists of two signal like a can high and can low. So here we have a high-speed can voltage level. So based on the specification, like this voltage level get varied. So it transmits differential signal through can high and can low. It has two state, dominant and recessive. So during dominant transition, can high is driven to VCC and can low is driven to ground. And during recessive transmission, both the can high and can low is driven, rest around 2.5 volt. This is how a signaling look like. And node, this is how a node look like. Basically it consists of three parts, one is microcontroller, second one is can controller, and third one is can transceiver. So microcontroller responsible for sending and receiving the message over can network and this can controller is intermediate between this microcontroller and can transceiver. So whenever any message arrived on the can bus, so this can transceiver, transmit this level to can controller and this can controller wait until the new message is arrived. So once a new message arrived, it triggers the microcontroller that, hey, I have a new message, please collect it. So then microcontroller will collect the new messages. So this is how a node will look like. And this is can bus architecture. Like in can bus architecture, minimum two node is required to establish a communication like to send transmit and receiving data. So here we have can A can be and up to can X. So number of can node is decided based on the cable length and data rate. Yeah. And so this can bus is terminated by a termination resistor. So it is connected between can high and can low. So it's used to to suppress electromagnetic interference and provide noise immunity to for data communication can message. It can protocol transmit message in from in form of frames. So it can transmit the message. It follows as a broadcast type, meaning any node in the network can receive the message and it has a capability to whitelist which message it interested in. For example, so far, take a particular message ID like one, two, three or four, five, six. If it is interested in one particular message, it can filter those message alone and it supports four different type of frames. One is data frame. Second is remote frame error frame and over overload frame and can message frame. So this is a general structure of can message frame. It consists of startup frame, frame header, control field, data payload, frame header and end of field. So basically there are two types of frames. One is a standard one. Second one is a extender one. The key difference between standard and extender is standard one is a 11 bit identifier extender is on a 29 bit identifier. Meaning standard one has a higher priority than extender can frame on the bus. So like so far we saw about a classical can later, Robert Bosch introduced a new specification called can FD. So here are the key differences between classical can and can FD. So data rate. Classical can sub to one megabits per second, where can FD supports up to eight megabits per second. The payload size is eight bytes payload per frame. Can FD supports up to 64 bytes payload per frame. Network length is 40 meter and can FD because due to its high data rate is network length is a limited to few meters. And again, the network length is based on number of nodes connector and data rate. Compactability classical can is not compactable with can FD, whereas can FD is backward compactable with classical can like meaning classical can transmit the data to can FD. Yeah. Okay, so far we saw about an can specification like architecture and bus architecture. Now we will concentrate on Zaffer driver model, like how the device hooks into Zaffer, like into the system. So basically it consists of four layers like application, can driver, can controller and can transceiver. So whenever a user sends any data from application, it will transmit via can driver and then can controller. It's often part of microcontroller. Sometimes it will be SPI connected. And again, this can controller transmit to can transceiver and vice versa. Zaffer also supports socket can based implementation, like it provides user to an interact with a can controller with the socket APIs, BST socket APIs like socket, send, receive, accept, bind, close, et cetera. So it is compactable with Linux socket based implementation. And this socket API is based on the Zaffer networking stack. So this is how the socket can looks like. So in between, it uses an networking code from the Zaffer. So how to add a can controller in the Zaffer? So first we need to check whether that is an existing driver or not. If it is that, then we can expand it or adapt it or otherwise we need to write our own driver. For example, first we need to define your device tree and then implement a driver. And if required, we need to write our own sample application and test cases. So like how the things are populated in most embedded devices like Linux and Zaffer are almost and always it's done by device tree. So if you already know about something about device tree, then you may familiar with this kind of a syntax. So here I took an mcp25, so which supports can over spy. So we need to use a spy. So that's why I defined, so that's why we need to define a spy node here and then corresponding chip select pin. And afterwards this, afterwards we need to define the can controller. So this can underscore zero is a device identifier for spy. So it's the first device connected over the spy bus. And below to that, we need to define the compactability and compactable driver and spy maximum frequency, intra pin and status. So this status controls whether this driver need to be enabled or disabled and rich property, oscillator frequency, bus speed, synchronization and sample point and maximum transceiver support like maximum bit rate it can support. So these are the properties are defined and that can load. So this is how a device declaration looks like. So I'm starting from the end of the file. So most of the information from the device trees are populated here and they struck mcp2515 underscore config. And next to that, so we need to define this API device dtins define. So it is initialized, it initialized during boot time and it creates a device object. So basically this macro requires init function, power management function pointer and data pointer, config pointer and which init level it needs to be initialized and initialization priority basically from zero to nine, 99 and function pointers for the particular driver. So in this case can. So here is the initialization function. So first we need to get the config and device data. And second, we need to like this mcp25 is connected over spy bus. First, we need to verify the spy bus is ready. So once it's ready, afterwards we can configure the interrupt and create a new thread. So basically this thread is used to handle the interrupt. So whenever any message is received, this can controller trigger the host controller with the interrupt. So this thread is used to handle that interrupt. And device specific implementation like setting modes like normal mode or loopback mode or some data rate. So these things are initialized here. So this API will return either zero or negative value. Next to do that, it's a function pointers like how we can interact with the can controller. So basically can underscore driver API provides a set of APIs like to get the capabilities, set timing parameters, start the can transceiver, stop the can controller, stop the can controller, set the mode, send the data and get the maximum filter rate, available filter rate and adding a new filter, removing a new filter. So these are the APIs the can underscore driver provides. So this is how an application looks like. So the first we need to know about the device identifier. So once we know about the device identifier, then we can get the device with this help of macro called device DT gate. So it will return the device structure. So and afterwards we need to verify whether this device is ready or not. So if it is not ready, so it will return return here. So this is come from this initialization function. So for example, if it is written zero, then this function, this if condition will, this if condition will pass, otherwise it will return here. And next we need to set the mode. For example, it supports normal mode and can loopback mode and other modes. So here I am setting the loopback mode. And next to that I'm starting, we need to start the can controller with this device pointer set timing. So for example, if we want to change our data rate during runtime, so first we need to calculate the timing parameter. So this timing parameter is calculated with the help of data rate and sample point. So here the data rate is around 250 kilobits per second. And sample point is 87.5 percentage. Usually the sample point is 87.5 percentage. So if it's calculates the sample point and return zero, then we can set the can, set the timing parameter by stopping the can controller. And afterwards we can set the can timing. Then afterwards we can enable the can controller with the help of a can underscore start. So this can underscore start will, like it will reset the previous errors and initialize the can transceiver ready to send and receive new messages. And next to that, send function. So basically, like with classical can, we can send eight bytes per frame. So there is a structure to define message ID, data length and data and flag. So here the message ID is zero cross one, two, three. So it is a standard ID and data length. I'm setting it as eight bytes. So here is the data. So this is a eight byte of data. And we need to use this can underscore send API to send this frame. So this API accept device structure can frame structure. And then timeout, timeout value. So last two argument is callback function. And last one is a user data. So this is a blocking API if it doesn't receive any acknowledgement from the any notes. So it will return negative value or else if it receive any acknowledgement, it will return zero. Until 100 milliseconds, it will wait for a, it will wait. Otherwise it will return a timeout error. So this is a non-blocking API. So the one major difference between blocking and non-blocking APIs, we can set our callback. And so whenever we call this API can underscore send, it will never wait for any acknowledgement or any errors. So this all handled in this tx underscore callback. So receiving, so how we can receive data from canned receiver. So first, like as I said before, can itself provide white listing or filtering the message, whatever we require. So we can set the, first we need to define which ID we want to, we are interested in. And what type of ID it is. So in this case it is a standard mask and that is an API can underscore add or X filter. So this will set this filtering function. So whenever any new data is arrived, so this will be available in this callback function or X callback function. But the user need to handle it in this callback function. So if it is a long, long, long execution, then we either we need to schedule a new work or switch to new thread here. And also it supports message to receive via message queues. So first we need to define the name and priority. So here the message ID is 1234567, it's an extender ID. And the API is same like before, but it is particularly for message, adding a message queue filter. So once it receives us a new message, like here is the infinite loop. So it will wait for a new message. So once a new message is received, this will execute further. So so far we saw about driver implementation and sample application. So the next main thing is how we can debug this can based project with some other tools. Like that is an open source tool available, which is called CanUtil. So it is helpful in debugging and testing even we can create a small prototype. So it provides us a set of tools like CanSend. So with this tool, we can send a single frame of a message and can dump. So it is used to dump the receive message or we can set the filtering option. Third one is a can gen. So it will generate random traffic in the network, can player. So it will, so with this help of an can player, so we can view the, log the data so and can snippet. So it is used to differentiate between the signals and can lock server. So this is a simple example to send and dump our data. So for example, we have our can also, which is based on the suffer and to debug this, to debug our Zaffer can node. So we need to have some single board computer like Raspberry Pi with can controller and can transceiver connector. So from that single board computer, we can send some can data to the network and we can dump the data. So if our Zaffer node sends any data, so with this help of can dump, yeah. Thank you. Any questions? Any questions? Yeah. Thank you for the presentation. As a new developer who's using can and we have some parts that currently support can. So if I am adding a derivative board, let's say, and I'm using existing drivers, what would be the best recommendation for testing? In terms of if I want to do a loopback, how much confidence can I have that the loopback is good enough implementation of this new target that I've implemented? You mean testing the new driver? Not a new driver, a new board that is using an existing driver. Okay, then the best way is to test with the some readily available setup like a Raspberry Pi. So for example, you need to configure it to normal mode. So it will transmit and receive the message over can bus and another opposite side, we will like you will have a Raspberry Pi. So it will receive that message. So that is the quickest way to verify. So the best would be to have two boards running running Zaffer. No, one is running with Zaffer. And the second one is some readily available single board computer. Okay, that seems. You want something to add? Yeah, I want to comment on this. Under Linux, you can use can gen not to only generate random data, but you can generate data with increasing content. So the data would be one, the next frame, the data would be two and so on. So you can sense this with configurable delay from a Linux system. And then on your Zaffer, you can check if you receive can frames with increasing content. For example, my question was we have some tests and samples in Zaffer. Right. So if I have to use, let's say any of those tests, do I need two boards to test? Definitely. I will recommend two boards to test. I'm not confident with this a loopback mode. So sometimes it will show false positive results. Right. So say I have one board that I know is good. You know, we have implemented can and it's working. I have another board that is my board that I've added. Can I use Zaffer running on both boards? Yes. Do I cross the wires? Is that all I have to do? Like run can Rx to can Tx? Yep. No, can as a bus you connect can high to can high and can low to can low and at a termination resistor on both ends of the bus. And then you can plug in as many can systems as you want to some extent. For example, you can test your two Zaffer boards sending data back and forth. And you can add another Linux system in between or at the end. It doesn't matter where and have a second opinion on what's going on the bus. Maybe quick addition to that. So the loopback tests, which are used in all the tests, internal testing in Zaffer, they are suitable for testing all the can controller stuff inside the MCU. But if the transceiver doesn't work, you would not realize. So then you would have to build up a whole system with the bus, I would say. Just want to relay on a comment from Sam Edge coming in from virtual. He's saying that because of the differential bus nature of can to do proper on the bus, on the wire loopback testing, you need to two can interfaces, either on the same board or two different ones. You can get can USB can interfaces for the PC, which can be driven from Python, specifically peak, total phase, cave asser, and can do. So just adding into that comment. So we do have a sample in that we have quite substantial API testing for the loopback mode of the various can controller drivers. As Martin mentioned before, if you go beyond the controller driver itself and want to verify a new board, as you're asking Mahesh, we have the sample, the can driver counter sample. And this does a ping pong of messages between two can controllers using the actual bus infrastructure. And you can do this between either two SIFR bus, two SIFR boards running this. You can use a USB to can controller connected to a PC. And you can actually do this. You can run the SIFR sample on the Linux as a native politics binary, and use that to access a native Linux socket can interface, accessing the USB can controller and doing the ping pong messages to the board. So this was added by Martin, the native Linux can controller a dash and layer. So we do have the means for doing what you're asking here, Mahesh. Thank you for the talk. It's been a while that I've done something with can, but if I remember correctly, typically can controllers can have written the filters into the hardware. The filters that you just showed, will that be also typically written into the can controller itself, or will it be executed in software? It's written into can controller itself. So it's not a software, it's a hardware. Thanks. And if we can just add it, it depends really, because some can controllers have a lot of these can RX hardware filters available, and some have like one. So the typical solution in server is if you have a small amount of RX hardware filters available, we do a software filtering, and this is supported by the can driver framework. So you basically just set the can controller to receive everything, like they do in Linux, and just regard the hardware filters, and then you do the filtering in software. This is of course less effective on a microcontroller than it is and in a larger CPU for Linux. So we generally want to avoid those controllers. Thank you. And if you found any issue, or if you develop any driver, please feel to open your new PR. And once again, thank you for joining.