Dec 13

In order to quickly add RoboCAN functionallity to any Delphi application I developed a RoboCAN component in Delphi 2007. The code is based on the test program as developed before, but the component itself is more inline with the AT90CAN implementation.

The RoboCAN component provides (next to the name) only one property called Speed. The baudates that are supported are the same as for the CANUSB interface and can be set at design and run-time. There are five events that match the call back functions in the AT90CAN code:

  • OnRoboCANBusError
  • OnRoboCANReceiveError
  • OnRoboCANSendError
  • OnRoboCANSend
  • OnRoboCANReceive

The first three events are to report bus, receive and send errors. The OnRoboCANSend is executed when a message has succesfully been send and the OnRoboCANReceive when a message is received. Both functions hold the RoboCAN message as parameter.

In order to test the RoboCAN component an application RoboCANCompTestApp has been developed. This application does not use a RoboCAN component in design-time. Instead, at run-time a RoboCAN component is created, this allows you to debug each code line of the component.

If you want to install this component, in Delphi 2007 open the RoboCANComp.groupproj project which contains two projects; RoboCANCompTestApp.exe and RoboCANPackage.bpl. If the project manager is not open, then open it using the View | Project manager menu. Double click on the RoboCANPackage.bpl project, right mouse click on the project and select the Install menu. This will add a palette Robotics with the component TRoboCAN in it.

If you want to make modifications to the component, double click om the RoboCANCompTestApp.exe project, if you now run the application you can step through the code of the component.

The source can be downloaded here, it will always be the latest version.

Dec 10

Based on the RoboCAN specification, I implemented the protocol on the AT90CAN and in Delphi using the CAN USB interface. For the AT90CAN it is placed in a second unit that makes use of the CAN.c unit I already wrote in order to process single CAN frames.

The logic behind the code is simple. It starts with a buffer of 1024 bytes called CANBuffer, this buffer is (only) used for storing the data of incoming and outgoing messages. The only clever part of this buffer is that a call can be made to ClaimBufferSpacewith a required number of bytes. This function will find the first consequatative block of bytes in the buffer that can hold these bytes and return a the position of the first bytes in the buffer. If message A takes 10 bytes, it will return BufferPos=0, message B takes 20 bytes, it will return BufferPos=10. If message is is completed and processed, this area could be used again. If a call comes in for message C that takes 12 bytes it will not fit since message B is not processed. As a result, BufferPos = 30 will be returned. The 1024 bytes is not based on any experience. Time will tell if this is too much or too less.

The next part is an array called MessageBuffer that holds 10 records of below data:

  • unsigned char FromAddress
  • unsigned char ToAddress
  • unsigned char Flags
  • unsigned char Command
  • unsigned char NumberOfBytes
  • unsigned char BytesProcessed
  • unsigned int   BufferPosition
  • unsigned char TimeStamp
  • unsigned char MessageID

The FromAddress and ToAddress hold the device address of the sender and the receiver. Flags is a byte that holds settings of the message and can be a combination of below bits:

  • mf_CommandFrame  0x01    b0, 0=acknowledgement frame, 1=command frame
  • mf_NormalFrame      0x02     b1, 0=interrupt frame, 1=normal frame
  • mf_Transmit             0x04     b2, 0=message buffer used for read, 1=for write
  • mf_Finished              0x08     b3, 0=message being processed, 1=finished processed
  • mf_Retry                   0x30     b5/b4, holds the number of retries during send
  • mf_Reserved             0x40     b6 is reserved, should be 0
  • mf_InUse                  0x80      b7, 0=message buffer is free, 1=busy

When a message is being send, the function FindFreeMessageBufferwill scan through the array and checks if the mf_InUse flag is 0. When sending a message, the search starts at record 0 and continuous upwards until a free one is found or when it exceeds number 7. Reason for this is that the record number is use as MessageID for sending the message, this will ensure that always an unique MessageID is used. When receiving the first frame of a message the search will start at record 9 and continuos downwards until a free record has been found. Also here the 10 records are not based on any experience. Time will tell if this is too much or too less.

When a message is offered for sending a free MessageBuffer is found and all the fields in the record will be set. A call is made to ClaimBufferSpace to claim storage capacity based on NumberOfBytesand the returned BufferPos is stored in the record after which all the data to be send is copied into the CANBuffer.

The actual sending of the seperate frames is taken care of by the funtion SendRoboCANFrame. When this function is called it scans through the used records in MessageBuffer  to find the message with the highest priority. When found, it determines how much packages are already send using the BytesProcessed field of the record and it configures a single CAN frame that will be offered to the CAN interface for sending. After this the BytesProcessed field is updated and the application can continue execution. When the byte is send the CAN interface triggers an interrupt and the Interrupt Service Routine will call SendRoboCANFrameagain repeating the process of find the highest priority waiting message. If no messages are waiting this process will stop automaticly since no interrupts will be triggered anymore. For that reason the function SendRoboCANFrame must be called ones by the function that submits a message for sending.

Receiving messages works in a simular manor except that there are 4 MOB’s setup in parallel all filtering for the same priority. This is to prevent frames are lost when more devices decide to communicate in parallel with the device. The number 4 is again not based on any experience.

Any frame that is addressed to the device is execepted in any of the 4 MOB’s. When a frame is received an interrupt is triggered and the frame is read. A function RoboCANFrameReceivedis called that checks if this is a frame using PackageNumber 0. If so, a free MessageBuffer  is found, filled in and memory is claimed using ClaimBufferSpace. Possible data is directly stored in the CANBuffer and the fields BytesProcessed is updated.

If a PackageNumber is used higher than 0 the previously used MessageBuffer  is found using the FromAddress field and the MessageID. Again the data is stored after which a check is done if the fields BytesProcessed  and NumberOfBytesare the same. In such a case the full message is received and an Acknowledgement message is send usign the same function for sending a message as the application will do: SendRoboCANMessage. This will stored the message using a MessageBuffer and store the data in the CANBuffer, the interrupt based SendRoboCANFrame will than take over based on the previous explained algorithm of finding the highest priority.

Since a message was fully received a callback function ProcessRoboCANReceived that holds a structure TRoboCANDataas parameter. The definition of the function is part of the RoboCAN unit, but the actual implementation needs to be included in the host application making use of the RoboCAN protocol. The passed variable RoboCANData holds all the data of the message:

struct TRoboCANData
  unsigned char Interrupt;
  unsigned char Acknowledge;
  unsigned char ToAddress;
  unsigned char FromAddress;
  unsigned char Command;
  unsigned char NumberOfBytes;
  unsigned char *Data;                 

The function ProcessRoboCANReceived is part of the Interrupt Service Routine that received the last CAN frame. By using such a callback function there is one point in the application were all commands come in at the moment they arrived. The downside is that all other CAN processing is on hold until the function completes so processing of the command may not take much time. Time will tell if this is a smart method, it can easily be converted to a non-interrupt version. When the function is completed, the MessageBuffer is freed and the data stored in the CANBuffer is lost.

The same process is used for reporting that a message has been send and was acknowledged by the receiver. At that time a callback function ProcessRoboCANSend is called as part of the ISR that received the acknowledge frame. Also here the original message is passed as a variable so that any post processing can take place or application status can be updated. When the function completes also here the MessageBuffer is freed and the data stored in the CANBuffer is lost.

During transmission things can go wrong. If so, the RoboCAN protocol will retry maximum 4 times (if possible) before finally reporting the error. For this a timer is used (TIMER2) that is set to trigger an interrupt every 25ms. Every 25ms the TimeStamp field is increased by one for all MessageBuffer s that are in use. If at that time it reaches the value 10 (so 25ms in total) the two mf_Retry bits in the Flags field are tested to see if the number of retries exceeded 4 time. If so, the message is canceled and an error call back function is executed. Whenever a message that is in progress has been modified from (for example) receiving or sending a single CAN frame, the TimeStamp field is set to 0 to show progress has been made.

There are three error callback functions, ProcessRoboCANSendError for reporting send errors, ProcessRoboCANSendError for receiving errors and ProcessRoboCANBusError for interface errors. Main reason for three different functions is that the parameters are different. On a send error the actual message is passed back next to the error. On receive errors the message has not been received, so only the device address that was trying to send a message is passed next to the error. On interface errors there is no message or device known, so only the error is passed.

The RoboCAN units for the AT90CAN can be downloaded here and a small application that shows how to work with the callback functions. It will be replaced by every new version, so you always have the latest one. For the PC a protocol test program has been developed in Delphi 2007 to test the protocol on how it handles errors. You can use it if you like, next to sending and receiving RoboCAN based messages it can also send and receive single CAN frames (of course). The RoboCAN framework will be re-used for writing a component so RoboCAN can easily be integrated in any Delphi based PC application.

Dec 9

It has been a while since the last post. Main reason for this is that I wrote a first implementation of the RoboCAN protocol in Delphi and for the AT90CAN controller. The global idea as defined in previous posts has stayed in tact but there are a few differences so below a new overview of the protocol.

A RoboCAN message consists of below data:

  • Interrupt, boolean
  • Acknowledge, boolean
  • ToAddress, byte
  • FromAddress, byte
  • Command, byte
  • NumberOfBytes, byte
  • Data, array of bytes

If the Interrupt field is set to true this message is send with the highest possible priority over the bus. It can even interrupts messages already in progress from the device itself. Only interrupt messages of devices with a higher priority (so a lower FromAddress) can interrupt this message. Although the number of data bytes can range up to 254 bytes it is good practice to limit the number of data bytes to 6 in which case the message only takes one CAN frame to transmit.

When a message is received by the addressed device, this device has to acknowledge the message by sending a message with the Acknowledge field set to true. In the message one data byte is included that holds the MessageID (will be explained later) that was used for sending the received message. As a result an Acknowledge message is only one CAN frame in size, this message will be send with a lower priority than Interrupt frames but with a higher priority than any other message. This message can also interrupt other messages from the device itself or from other devices.

The ToAddress holds the address of the device to which the message is addressed, it can range from $00 to $FF allowing 256 devices to be connected on the CAN bus at the same time.

The FromAddress holds the address of the device itself so that the receiving device can reply with an Acknowledge message. Also this field can range from $00 to $FF.

The Command field can be defined by the application and can range from $00 to $FF. It is expected that a set of fixed commands will be defined (e.g. GetStatus or GetVersion) that each device must include in it’s application. These commands will start at $FF and decrease with every new command allowing the custom application to start at $00 and increase with every custom command. This will limit the impact if new standard commands are added over time since there is a big chance that the commands are not used yet by the application.

The NumberOfBytes fields holds the amount of data bytes that are stored in the message, this can range from 0 to 254. If more than 6 data bytes are stored in the message the RoboCAN protocol will split the message in multiple frames. Any frame after the first frame can hold 8 data bytes limiting the amount of required CAN frames to a minimum.

The actual data to be transferred is stored in the Data field, this is a consequative buffer of bytes with a maximum of 254 bytes in total.

RoboCAN is a multi-master protocol, any device can send data to any device. If a message is send the receiver must acknowledge the message within 250ms. If this is not done the full message is send again up to 4 times. If a that time there is still no acknowledge, an error is reported to the application.

A message that consists of multiple CAN frames is send in a chronological order so the receiver can store the data of each frame after each other and pass the total buffer of data to the application when all data bytes are received. However, messages that are send from higher priority devices to this device will interrupt the data stream from the previous lower priority sender. Also Interrupt and Acknowledge messages to and from this device will interrupt the data stream. If the time between each CAN frame that is part of the single message exceeds 250ms the sender will stop sending and the receiver will discard the received data so far. The sender will retry to send the message when the CAN bus is not in use up to 4 times.

All messages use the extended 29-bit priority fields. The bits are mapped on to of the various message fields as listed below:

  • b28, 0 = Interrupt, 1 = Normal message
  • b27, 0 = Command, 1 = Acknowledge message
  • b26..b24, Reserved for future extension. Should be 0b100 for now.
  • b23..b16, Toddress
  • b15..b8, FromAddress
  • b7..b5, Message ID
  • b4..b0, Package number

Most fields have been explained except for the last two. Since a message that is being received can be interrupted by frames form a higher priority message the sender includes a Message ID ranging from 0 to 7. This allows the application to send two (or actually eight) messages in parallel to verious devices without waiting for the first message to be completed. It also means that two (or more) messages can be send to the same device without waiting for the first one to complete. If the MessageID was not included the receiver can not see which frame belongs to which message. Please note that Interrupt and Acknowledge messages are included in the maximum of 8 messages.

This situation will be very common, for example if a command has been send from device A to device B requesting a measurement to be executed and send the results when completed, device B will send an Acknowledge message. This message does not mean the command has been execute, it only means the command has been received. Than device B receives a message from a higher priority device C to do something.  When the measurements are completed the results are send from device B to device A. This message may take several frames, during transmission of the results device A may already send a new command to device B. This will result in placing the transmission of the results on hold since the Acknowledgement message has a higher priority. So the result message will use MessageID 0 and the Acknowledgement message will use MessageID 1. After the Acknowledgement message the command from device C is completed and also requires data to be send. Since this is send to a device with a higher priority than device A the message to device A is placed again on hold until the message to device C has been send.

The last field is the PackageNumber, since a message can contain 254 bytes of data this number indicates which part of the data is included in the frame. The first frame uses PackageNumber 0, the first data bytes is the command and the second data bytes is the total amount of data bytes in the message. The last 6 data bytes can already be used for actual data. The receiver will only accept a new message from a sender if the PackageNumber is set to 0. At that time it can calculate how many frames will follow and how much memory must be allocated to store the incoming data. The next frame using the same FromAddress and MessageID must use PackageNumber 1, after this 2 and so on. In total there can be 32 frames, so (32*8)-2=254 bytes of data.

Nov 17

In order to develop the higher level RoboCAN protocol I will need two devices that are connected to the CAN bus. One is the ATDVK90CAN1 board and the other one is a PC using the CANUSB interface. When the drivers are installed a series of demo programs is installed as well including the source code. These demo programs show how to interface with a DLL called canusbdrv.dll which provides the basic functions to send and receive frames using the CANUSB interface.

I’m using Delphi 2005 as my development environment for Windows applications. Opening and compiling the SDIAPP stored in the C:\Program Files\LAWICEL\CANUSB\examples\Delphi2005 folder works, however when executing the code it crashes when I press the openbutton. I wonder if it truly is so difficult to build code that works…

Some debugging later I find that the string used for receiving the version is too small for storing the version. Below is the modified code (the bold parts):

procedure TSDIAppForm.BtnOpenClick(Sender: TObject);
Var VerText : String[255];
  Label1.Caption := VerText;
  BtnOpen.Enabled := False;
  BtnClose.Enabled := True;
  BtnStatus.Enabled := True;
  BtnWrite.Enabled := True;
  Timer1.Enabled := True;

Next to this, I changed the address used for sending frames to $310 so it works with the code running so far on the ATDVK90CAN1 board. Now at least it does not crash, however when pressing the write button I see that a frame is received with 1 data byte (correct) but it shows two… Some more debugging shows that the loop to show the received data contains another bug as well… Below the modified code (the bold parts). 

procedure TSDIAppForm.Timer1Timer(Sender: TObject);
  CANMessage: CANmsg;
  DummyStr: String;
  tmp: Integer;
  if (CANUSBRead(CANMessage) = ERROR_CANUSB_OK) then
     DummyStr := Format(‘ID = %x,’, []);
     DummyStr := DummyStr + Format(‘ LEN = %d, DATA = ‘, [CANMessage.len]);

     tmp := 0;
     while (tmp < CANMessage.len) do
         DummyStr := DummyStr + Format(‘ %2x’, [[tmp]]);
         Inc (tmp);

     Label3.Caption := DummyStr;

procedure TSDIAppForm.BtnWriteClick(Sender: TObject);
Var CANMessage: CANmsg;
begin := $310;
  CANMessage.flags := 0;
  CANMessage.len := 2;[0] := $55;[1] := $AA;

At least it seems the ddl is working so I will use this dll to develop a RoboCAN monitor application.

Nov 16

Next to the priority of the messages, also some though should go into the library that implements the protocol.

Sending a single frame will require about 110 bits on the CAN bus. Using a 500kbps speed this will take 220us limiting the total amount of frames to 4500 frames per second. Question to answer is if it is necessary to buffer multiple outgoing commands or is it enough to buffer one command and report back to the application it has been send before another command can be send. Based on the 4500 frames per second and assuming that an average command will require 3 frames (2 for the command, 1 for receiving the acknowledgement) it means transferring the command will take a bit less than 1ms.

But what if other higher priority devices are on the bus transferring data? What is they decide to transfer larger amounts of data? If the send command function would only return when it has completed this would be a problem, however the transfer is already interrupt based. So the send command function can return directly allowing the application to continue. Before a new command can be send a verify must be done if the previous was already send. If not, than there are again two options: than wait in the send command or return with an error code. From an application point of view, most cases you want to wait before continuing. Also in most cases the command will result in data being send back that than must be processed. But the difficulty lies within the most.

Best approach here is to pass an additional parameter to the send command that indicates when to return: directly or when the acknowledgement has been received. If the previous command has not been send, than it overrules the parameter and wait until the previous command has been send. In both cases a time out must be implemented on the maximum time allowed to wait before the previous has been send and a timeout must be implemented how long it can wait for a response. Next to a level of retrying of course.

The send command will return a status like OK, timeout, bus error and so on. Applications can than make the send command part of an if structure that is only execute when the send command was successful. If the option is selected so it return without waiting for the acknowledge, than it will return also with the OK status (if indeed it was executed OK). After this other actions can take place, if a t a certain time the application wants to check if the data actually has been send the global status field can be tested to see if it already has been send or that the acknowledge has been received.

In this assumption there is one part missing, when a command is received from another device it must be acknowledged by sending dummy data or the actual data that was requested. Since the process of receiving data is interrupt based the moment in time that data must be send is not defined. It can be just at the moment that the application also want to send a command. Or even worse, the command received might require some measurements that some time before a response can be send. Since the application is not processing incoming commands at that time there sure will be a timeout on the sender side which will “think” the transmission failed and it will retry.

Hmmm. This means any incoming command must be acknowledged for received, not for processed. When the application finally has time to process incoming requests than it send out the formal response (if needed). The problem of acknowledging data on time might also be encountered when a higher priority device decides to start communicating. It might be that these two items already use one of the reserved bits: the acknowledgement bit. By using this bit acknowledge frames will have a higher priority over the bus than command frames. Since the acknowledgement frame is only 1 frame long (potentially no data at all) this does not have a big impact on transferring larger commands but it prevent retries.

As a result, the 29 bits of the priority field are used as indicated below:

  • b28:          0=interrupt packet, 1=normal packet
  • b27:          0=acknowledgement packet, 1=command packet
  • b26..b24:  Reserved, should be 0b011 by default
  • b23..b17:  Address of receiver, 0×7F is lowest priority, 0×00 is highest priority device
  • b16..b10:  Address of sender, 0×7F is lowest priority, 0×00 is highest priority device
  • b9..b5:      Packet number, 0×00 is packet 1, 0×1F is last possible packet 32
  • b4..b0:      Total number of packets, 0×00 is 1 packet, 0×1F is maximum amount of 32 packages

The function that will handle incoming frames will than also be responsible for sending the acknowledge frame when a full command is received. After this, the command can be placed in a buffer and a flag can be set in the overall status that a new command has been received. This buffer needs to be able to hold several commands, it must also be able to handle several incoming commands at the same time. For example, when a command exists out of 6 frames it can be that after receiving frame 3 a new command is received from a higher priority device. Than in theory it is possible than the lower priority sender does not get an acknowledge and retries making the partially received command obsolete.

A single command can exists of 32 frames. This would require housekeeping if all frames have been received before a command is acknowledged. The sender can make sure that all frames are send in the right order, so 1 out of 3, 2 out of 3 and finally 3 out of 3. When the last one is received, the receiver can store it in the incoming command buffer and send an acknowledge frame to the sender. If reception is interrupted by a higher priority device and a timeout on the sender is triggered to resend the command, the receiver will suddenly receive 1 out of 3 again. At that moment, all previously received data from that sender can be ignored and deleted.

While processing an incoming frame the MOB is disabled, since it might take some time to process the MOB there must be more MOB’s monitoring the bus for incoming frames. This again presents a problem since this can mean that frame 3 out of 3 is processed before 2 out of 3 since the first one can be received in a lower number MOB and as a result is processed earlier if two frames have arrived before the processing starts. The solution for this problem can be a 32 bit wide variable in which each bit indicates if a frame has arrived. Only when all bits are 1 that should be 1 for matching the total number of frames than the command can be acknowledged.

The buffer that holds the incoming commands can be a simple list of “x” commands each claiming 255 bytes of possible data. In an embedded system were RAM is limited this should not be done, also the chance that all commands actually have 255 bytes of data is very limited. Instead, a linear FIFO buffer can be used that holds all received commands in a circular buffer. The receive function must claim the number of bytes in the buffer when the first frame of a new command is received. The amount of bytes is a sum of:

  • 4 bytes for storing the bit pattern to detect if all frames are received
  • 1 byte for the address of the sender
  • 1 byte for the command
  • 1 byte for storing the amount of data bytes
  • n bytes for storing the data

The circular buffer holds two pointers, one is pointing to the first free memory location and used for receiving commands and one is pointing to the first received command and used for reading. Since multiple commands can be received in parallel a function will be needed to claim memory (and so advance the incoming pointer) and return the original buffer location. When memory was claimed but the frame was canceled than it should be made invalid so that when data is read from the buffer this frame is skipped.

In order to read data, the first thing to do is to see if all frames are received. This can be done by checking if the number of frames to be received are reported as 1 in the first 4 bytes. However, an easier way is to check if all 4 bytes are 0xFF. If not, all frames are not received yet. That leaves the problem of how to detect if the received command has been aborted and so should be ignored and the memory released. This could be done by clearing all 4 bytes, this pattern is never used since the moment the first frame of a new command comes in one of the 32 bits (in most cases the first) will be set to one directly when the memory is allocated on the buffer.

Sending the acknowledgement frame can be done using a seperate MOB, since the acknowledgement frames have a higher priority than command frames there is no need for a second MOB.

The function that sends commands can indeed send frame by frame until all data is send. Than a timer needs to be started after which it can wait for an acknowledgement frame to be received. There is a timer available in the CAN controller, this can be used here since only one command is send at the time. When the acknowledgement frame arrives the senders address can be compared with the original to address. If they match, success can be reported. When the timer expires the whole command must be resend. It is possible here that just when the timer expires and the resend start the acknowledgment frame comes in. In that case it must be ignored. If after x (3?) retries the command still is not acknowledged than it is time to stop the transfer and report an error. If at that time a new command is send to another device to report a non-responsive device it is in theory possible that just at that moment (before or during sending of the new command) the acknowledgement still comes in. Since it is too late, it should be ignored as well. So there is only a specific time window that acknowledgement frames are used and at that moment they whould match the last used to address. 

Above results in:

  • 1 MOB for sending commands only to make sure frames are send in the right order
  • 1 MOB for receiving acknowledgements, only one needed since it will wait with sending the next command until this command is acknowledged
  • x MOB’s for receiving incomming commands. The number depends a bit on how much code is required for storing the incoming data compared with the time needed for receiving a new frame.
  • 1 MOB for sending acknowledgements

Time to stop now and think about it for some hours before implementation starts.

Nov 16

On top of the basic CAN interface I will add a communication layer that allows devices to send each other commands. I will call this communication layer RoboCAN and will use it in all my robots (at least that is my intention while writing this).

The amount of data that is part of the command should not be limited to the standard 8 data bytes that can be stored in a single CAN frame. Next to this there is a set of basic commands that each device must support, from example GetStatus. In most cases the sender want to be sure the command has been received so any command send must be acknowledged by the receiver. This acknowledgement is only required when a command is received for sending data. When a command is received for receiving data the acknowledgement is the response itself. This response does not have to be acknowledged by the original sender, if this sender did not get the response it will repeat the original request again.

In order to support sending a command to a device it will be necessary to give each device an unique identifier. A device only needs to respond to commands send to it, not to commands send to other devices. The unique ID can be stored in the priority field of the frame. The benefit of this is that the priority filtering mechanism can be used which reduces the software overhead of the device application. A second benefit is that this automatically provides a priority mechanism between the devices. On a busy bus, messages send to a device with a lower identifier value will have higher priority and other data will (temporarily) be put on hold.

Big question to solve it how to handle the transport of data block larger than 8 data bytes? In principle this can be solved by storing in the data fields something like frame x out of y frames. This presents some problems. For one, next to the command it will consume 3 out of the 8 bytes available, so a relative large overhead. Next to this, if the application send two commands directly after each other, how will the receiving device know which frame is part of which command? If an error occurs during transmission of a frame it will be resend, but at that moment another message can have higher priority, the sending order does not have to match the receiving order (like in HTTP). This would require a “command ID”, so consuming in total 4 bytes out of the 8. We can reduce this overhead by limiting the maximum to 16 frames, so x out of y frames can be packed in a single byte. The same can not be done for the command, I guess complex devices will have more than 16 commands. For the command ID it can be done but there is no other byte available to combine it with.

The priority field of a frame is 11 or 29 bits (CAN rev A or B). Using the 11 bits this would mean 2048 devices on the bus. I guess this is a bit much, perhaps we can use a range of priorities per device. For example, limiting the number of devices on the bus to 127 (7 bits) gives us 4 bits per device, so 16 “addresses” per device. Next, in the driver an implementation can be made that commands are queued, a new command can be send before the previous has been finished but is placed on hold in the driver until the previous command is fully handled. The 16 addresses can not be used for commands since 16 commands is not enough. For sending multiple frames for data this might be different.

The CAN controller itself provides an additional priority structure. When one or more MOB’s are enabled and the bus is free the CAN controller will first check if MOB0 is enabled. If not, than MOB1 and so on. So, if a command needs 3 frames for sending it’s data it can be placed in MOB0, 1 and 2. Only when MOB0 has been successfully transferred MOB1 will be send. However, this does not guarantee that the frame send by MOB0 has been received by the device. It is possible that the CAN controller was disable for a while on the receiving device, as a result it receives the frame send by MOB1 and MOB2 only (in that order). MOB0 frame is gone forever.

This does however provide a benefit, the order of frames can be controlled making the x in x out of y obsolete. The receiving device will receive part 2 out of 3 first, it thinks this is part 1 out of 3, since the other 2 parts have not been received yet it does not send an acknowledgement. Than comes part 3 out of 3, this is received as part 2 out of 3. Again no acknowledgement which triggers a timeout on the sender. The sender will than resend the whole message and than it goes wrong because part 1 out of 3 is received as part 3 out of 3…. Hmmm, this would require again the command ID allowing the device to see a new command is being send and so ignore all previous data.

While thinking about this, another problem is that when two devices start sending a command to the same device. Depending processing speed and the content of the data fields it can result than frame 1 is received from device 1 and frame 2 from device 2, theoretically using the same command ID. There is no way to differentiate between to senders, so the senders address must be part of the message somewhere. This also allows the receiver to send back the acknowledgement to the sender.

The problem of two senders in parallel can only be solved if each frame contains the sender of the frame. In total that means every frame should have:

  • The destination address
  • The senders address
  • Packet number
  • Total number of packets

This can also be done using a 29 bits long priority identifier in stead of the 11 bits. Above order can than also be used as priority information: A device with a higher priority gets data faster than with a lower priority. If two devices want to send data to it, the sender with a higher priority wins and the first packet is send before the last packet. Since the number of packets is always the same this has no impact.

Having more than 128 devices on the bus is not likely, so 14 bits will be required for the two address fields. This leaves 15 bits for the packet fields, also here 2 times 7 bits should be enough. As a result, 1 bit is free for which no function is defined yet. It might be a good idea to make this the most significant bit so it can be used later for even higher priority messages like alarm status or “interrupts”.

Since all required data for package transfer is now included in the priority field, all 8 data bytes are available for data. Except the command of course, so this is the first byte of the first frame. Also the total number of bytes that are included in the command (different than the number of packages) needs to be included, this will be the second byte of the first frame. As a result, there are 256 possible commands that each can include 255 bytes of data. Small calculation, since there are 7 bits to indicate the number of packages so a maximum of 127 packages. In total this allows us to send (127*8)-2=1014 bytes of data which is more than the 255 bytes previously mentioned.

If the limit would remain 255 bytes, the maximum amount of frames would be (255+2)/8=32.125 so 33. This would require 6 bits for storing the amount of packages instead of the previously indicated 7. This leaves 3 bits reserved for future use. Since the amount of packages will always be 1 (or more) the bit pattern 0b000000 can be used as well to indicate packet 1. When using 6 bits for the amount of packages this means we can send 32 packages, so (32*8)-2=254 bytes of data. The maximum was 255 (the value 0 is a valid number as well), so one bytes less might be a good compromise to save another 2 priority bits bring the total number of reserved bits to 5.

This brings up an interresting debate, if we limit the amount of devices to 6 bits so to 64 than we have 7 bits that can be used for storing the command and as such increase the maximum number of data bytes to 255. The advantage is that we can include the command in the priority, the dis-advantage is there is no reserved bits anymore. Is the command in priority higher than a sender? The sender can control this by itself, so the command should than be placed between “to address” and sender address making it possible for a lower priority device to interrupt a higher priority device with a higher priority command. Confused?

The only reason to do this is so (indeed) interrupt somebody. For this 1 bit should be enough. Secondly, each device must support a basic set of commands which than should remain constant in time, but the true priority can only be set during design time and can vary over projects. So this is not a smart thing to do. So the conclusion is we remain using 7 bits for the device addresses and using the first byte in the first packet as the command.

The interrupt feature is an interesting one, it is not a real time interrupt, but it will be beneficial to use the highest bit for this. If two high priority devices decide to exchange larger amount of data this can result in many frames before a lower priority device can actually report it is in panic mode… If used sparingly this adds value. Also here the interrupt of a higher priority device wins over an interrupt of a lower priority device, all very logic.

As a result, the 29 bits of the priority field are used as indicated below:

  • b28:          0=interrupt packet, 1=normal packet
  • b27..b24:  Reserved, should be 0b0011 by default
  • b23..b17:  Address of receiver, 0x7F is lowest priority, 0x00 is highest priority device
  • b16..b10:  Address of sender, 0x7F is lowest priority, 0x00 is highest priority device
  • b9..b5:      Packet number, 0x00 is packet 1, 0x1F is last possible packet 32
  • b4..b0:      Total number of packets, 0x00 is 1 packet, 0x1F is maximum amount of 32 packages

The reason for the 0b0011 pattern on the reserved bits is that this allows future expansions using a higher and a lower priority.

I will write a library that implements above to get some experience with this structure.

Nov 12

As previously already mentioned, I like to go into details to fully understand how things work. Also for working with the CAN protocol, I want to understand how this works and how the AT90CAN CAN controller supports the interface.

On the CD-ROM that comes with the ATDVK90CAN1 there is sample code including a simple CAN driver that allows you to send and receive a frame. Next to the fact the code is very cryptic and it is not interrupt driven I want to write my own low level code so I truly understand the CAN modules and can solve problems later on that are related to the CAN interface.

The first version of my code can be downloaded here, the most important part is the CAN.c unit. This version is purely to provide the basic level of sending and receiving frames and respond to the various interrupt sources of the CAN controller. If you want nothing more than the basics, this is a good start for generating your own code, I think I will add an extra layers so applications can simply read and write “data” to a specific device similar to the CANOpen protocol. I will not use the CANOpen protocol since it only accepts one master on the bus, I want every device to be a master.

The AT90CAN controller handles almost every task needed for sending and receiving frames. It can handle 14 frames in parallel, for this it uses 14 so called Message OBjects. Each object can be setup to receive or transmit a frame. If something goes wrong during transmission an error interrupt is triggered but all error handling is done by the MOB itself. It continues to retry until it is successful or it fails to many times as defined by the CAN protocol. At that moment the bus is automatically disabled for sending and/or receiving depending the error.

So all that is needed for sending a frame is to find the first available MOB that is not busy, fill in the message priority, the maximum of 8 data bytes and set the mode to sending. After this the CAN controller will do the rest as soon as the CAN interface is not used. When finished, it triggers an interrupt and automatically disables the MOB keeping it locked until the application manually frees it.

For reading a frame this works similar with the exception that now the base priority needs to be set in combination with a filter that sets a range around the base priority. When a frame is received, the filter is used to check if it should be passed to the application or not. If a specific bit in the filter is set to 1 that same bit in the received priority has to match the bit of the base priority. In case of a 0 in the filter the matching bit in the received priority is ignored. As examples:

To accept only message priority 0x317:

  • Base priority  = 011 0001 0111 b
  • Filter              = 111 1111 1111 b

To accept priority from 0x310 up to 0x317:

  • Base priority  = 011 0001 0xxx b
  • Filter              = 111 1111 1000 b

To accept all priority from 0x000 up to 0x7FF:

  • Base priority  = xxx  xxxx  xxxx b
  • Filter              = 000 0000 0000 b

Also here, when it receives a frame matching the base priority and filter it triggers an interrupt and automatically disables the MOB and waits for the application to read the message priority and received data. After this, the MOB can be freed or enabled again for reading using the same filter.

In total, very simple. The only complex part is initializing the CAN controller or actually setting up the required baud rate. The whole timing of receiving a single bit of a frame can be defined using three registers. Luck ally the most common settings for these registers in combination with the crystal frequency and the required baud rate are listed in chapter 19.12 of the specification.

The logic of my code is that each MOB can be used for any action (send or receive). When an action is required the first free MOB is found and assigned to this task, any action later on (like reading the data when it finished receiving) uses the assigned MOB. When it is no longer needed, it must be released so it can be used by a new action.

In order to test it, connect the CANUSB to the PC, use the cable to connect the CANUSB device to the ATDVK90CAN1 evaluation board. Start CAN Monitor Lite, click the Open CANUSB device button followed by the monitor button. Execute the code in AVR Studio 4 in combination with an AVR JTAGICE mkII JTAG interface. The LED’s on the evaluation board should all be off.

Fill in the value 0 in the CAN ID field of the message tab in CAN Monitor Lite. Press the send button, a green flash should be visible on the CANUSB device. If a red flash is shown as well (or continuous red) there is a CAN bus error, check the cable and make sure the application in the AT90CAN is running.

The LED’s on the evaluation board should not change to indicate a frame has been received. Reason for this is that both MOB’s (MonitorMOBOne and MonitorMOBTwo) that are reading will see the frame passing by but it does not pass the filter in both MOB’s. When you enter 310 in the CAN ID field and press the send button again a small green flash will be visible on the CANUSB and the LED’s on the evaluation board will display the value 1. In this case MonitorMOBTwo has received the frame and is enabled again after reading the data. A (modified) frame will be send by the AT90CAN as a response and CAN Monitor Lite will show the incomming frame. Sending priority 311 will also result in the same effect since it can pass through the filter of MonitorMOBTwo.

Sending priority 317 will also result in the same effect but now using MonitorMOBOne. After reading the data it is not renewed, so sending again priority 317 will not show an incomming frame.

The filter mechanism is very powerfull in combination with the 14 MOB’s. You can also setup two MOB’s using the same base priority and filter. This reduces the risk of missing the second frame if the first frame is not read yet. This is important to understand since there is no active acknowledgement of data, even the opposite, messages are just being dumped on the bus without caring if somebody does anything with it. This is something that the next layer on top of these basic commands must take care of.

Nov 1

The development kit of the AT90CAN controller and the CAN USB interface arrived earlier his week. In order to setup an development environment on a Windows XP machine, follow below steps:

Download and install AVR Studio 4(version 4.14, build 589 at the time of writing). This will create a folder c:\Program Files\Atmel with all files related to AVR Studio.

Download and install WinAVR, when it asks for the folder for installation, select the folder c:\Program Files\Atmel

Download and extract the ZIP file of the CAN USB FTDI drivers (Virtual COM Port and D2XX DLL). Then connect the CANUSB to an USB port. When Windows starts the Found New Hardware Wizard, do not allow it to connect to Windows Update, select the No, not this time option. Click Next and select the Install from a list or specific location option. Click Next and select the Search for the best driver in these location. Only check Include this location in the searchand select the folder the holds the unzipped drivers. After installation of the device drivers, Windows will start again the Found New Hardware Wizard. This is to install a virtual COM port for the CAN USB hardware. Repeat the exact same procedure as above so the device drivers from the ZIP file are loaded.

Download and install the CAN USB & Active X Driver, this installs demo applications and an DLL that is used for using the CAN USB in your own applications.

Download the executable of CAN Monitor Lite. You do not need to install it, it is an executable already. Store it somewhere in c:\Program Files and create a shortcut to the desktop in order to start it. This is an application that uses the above DLL and shows all CAN frames that are send over the bus. It also allows you to transmit a frame with the maximum of 8 data bytes. Since the CAN USB hardware is connected to the PC, start the application and select the CANUSB | Openmenu. If this does not give an error message and at the bottom it states CANUSB Version: xxxx followed with Opened and the bit rate than the whole chain is setup correctly. A second test is to press the send button at the bottom the send a frame (no need to change the default data), since there is no one to respond a red LED will light up on the CAN USB hardware. After selecting the CANUSB | Close menu this LED will dim again.

Download and extract the ZIP file with the AT90CAN128/64/32 Software Library and Examples. This contains (amongst others) the basic CAN library to send and receive frames.

All installation work is now done, it’s time to start connection the hardware starting with the CANUSB and the ATDVK90CAN1. For this a cable must be constructed, below image shows the pinout of both male SUB-D9 connectors.

A CAN bus must be terminated at the start and the end of the lines by connecting an 120 Ohm resistor between the CAN_H and CAN_L pins. Combining this and the possible option to add a third CAN device later, below schematic shows how to wire a cable. Please note that only on one connector the shield is connected to ground. If you connect all shields to ground you are creating a second path for the ground line other that the ground line of the power supplies. As a result, you create a huge antenna and can be guaranteed to received all kinds of noise that is available in the air.

Below an image of the cable assembly, the termination resistors are inside the connectors. Each cable segment is about 50cm, so in total the cable is 1 meter long.

I will not connect the ATDVK90CAN1 board yet but first will try if I can program it with the JTAG. Reading the manualand checking all jumper default settings I understand there is a default program in the AT90CAN that does something with the LED’s and the buttons. After connecting the power plug, applying 8V and setting the power switch in the on position the green power LED lights up. Pressing any of the navigation buttons however does not show anything.

To verify that the AT90CAN is running, I verify if 5V is available. That is the case. Than it might be that the AT90CAN is not programmed, for this the JTAG needs to be connected. When trying to insert the 10 pins JTAG header in the connector the ISP pins are in the way. The pictures are not clear in the manual, it might that they cut them away. I will not totally remove them, but cut away the top 2mm of every pin. After this, the JTAG can be connected.

After starting AVR Studio and selecting the Tools | Program AVR | Auto Connect menu option followed by selecting the AT90CAN128 and JTAG mode in the Main tab followed by a click on the Read Signature button I see that the AT90CAN is responding in the status area. That means the board is not defective, good. In the Fuses tab I see that the clock select is set to an 8MHz external oscillator, this matches the settings of the jumpers as well.

After reading the FLASH file from the AT90CAN, saving it to disk, closing the connect dialog and opening the HEX file, AVR Studio will create a project allowing me to execute this HEX file step by step. Executing the HEX file by stepping through the code using F10 I do not see execution that looks like the demo program, no input or output calls are made. It looks to be some kind of boot loader program instead.

Since the source code is listed in the manual, let’s try to compile this demo and execute it. Start a new project and select Atmel AVR Assembler as the project type. Select the JTAG ICE II as programmer and an AT90CAN128 as target. Copy the example code and press Assemble and Run. Now pressing the center button of the navigation keys shows an LED moving until you release the button. I will send a mail to ATMEL so they can correct this mistake, if they (or you) want they can download the project here.