Dec 15

Some IO pins on the FB have separate pins for input and output. For example, input 1 on port G is available on pin J6.24 while the output 1 of port G is available on pin J6.23. On most controllers all pins are bi-directional, outputs are internally fed back to the input buffer so when you set an output and read the port status it shows the current output state.

On the FB this seems to be different for certain pins, to verify if indeed there is no internal feedback line a small test setup is made. A 220E resistor is connected to J6.40 (Vdd) and to the anode (+) of a low current LED. The cathode (-) is connected to J6.23 (OG1). The LED lights up, so this means the output is low. A separate wire is connected to J6.1 (Gnd) and so far not connected on the other side. This will be uses to apply a low level to J6.24 (IG1).

Using a SSH terminal to the FB, type the command setbits -p g -b 1 -s 1, this will set bit 1 on port g to a high level and the LED will switch off. Using setbits -p g -b 1 -s 0 the low level is put back and the LED will light again.

The command readbits will display a bit pattern of all the available ports a, b and g. The most right one using 32 bits is of port g, MSB on the left, LSB on the right. The 2nd most right indicates the state of IG1, with the wire disconnected this is a high level. When inserting the wire into J6.24 and repeating the readbits command indeed the level is now 0.

The final test is simple (but almost no longer needed), set OG1 to 1 and keep the wire inserted. The LED will switch off, using the readbits command will still show IG1 is 0. Conclusion, no internal feedback so the suggested use for the interface between the FB and the primary motor cortex is possible.

Dec 14

The RoboCAN interface was developed to provide a fast serial link between the Primary motor cortexand the various sensors and actuators acting like a spinal cord. The second interface needed is between the primary motor cortex and the brains: the FOXBoard.

The initial plan was to have a memory mapped interface using available IO pins on the FB. Using an 8-bit address bus would provide 256 unique locations. Each location could indicate a specific command resulting in 256 commands, writing to a specific address could trigger that command using the 8-bit data as a parameter.  Although this looks to be enough I’m not sure it will be for two reasons:

  • Command most likely require more than one data byte
  • The 256 address locations will need to be divided over more than one add-on board

Without a good solution for above two problems, it would be better to use some sort of serial protocol were more bytes are written to a specific location.

While writing above statement, this can actually be a solution for the first problem. If indeed each memory location is a command but it requires more than one data bytes, why not write more than ones to this location and only execute the command when all bytes are received? If the amount of bytes is know for each command than there would not even be a need to include a NumberOfBytes parameter. Simply start counting bytes and when the amount required has been received than execute the command. If on the same address additional write cycles are detected, assume these are for a new command. The same principle can be used for a command that reads data from the add-on board. If two data bytes must be read, two read cycles from that location are required.

Using this solution already reduces the severity of the second reason. Now there are actually 256 individual commands to be divided over several add-on boards. Since most micro controllers that will be on an add-on board are of the AT90CAN series it would be an option to increase the number of address bits since there is plenty of IO pins on such devices.

On Port G on the FB IOG8..IOG15 provide eight consecutive bi-directional pins for the data bus. The next eight IO pins IOG16..IOG23 can be used for the address bus, these are input/output pins but than only used as output. Since from a software point of view you do not want to split the address over various bits on port G additional address pins than should use IOG24, IOG25 and so on. IOG24 is free so this increases the amount of command to 512. Pin 25 is split into I25 and O25. I25 is used for an USB interface, so it would not be wise to use this one. On the other hand we need an output and O25 is free increasing the amount of commands to 1024 which would take away my worry.

I’m not sure how this split between input and output is made, they are on different pins on the connectors (pin J7.14 and J7.13) so it seems that these are two pins on the processor were the read or write access determines which pin is used. But this worries me since it states that software defines which pin is used, so if some software block is added that uses the USB interface you can get conflicts between my software and the USB software each configuring this signal. Checking the schematic of the FB shows that the USB connectors that are soldered on the board use USB1 and USB2 so these pins are in use.

When searching for the schematic, I also found how to make use of the IO pins in software. It seems you can not directly write a value to the IO pins, there is a function to set a pin and a function to clear a pin. I guess this makes sense since there are multiple processes working on the port in parallel. A normal read-modify-write action would not work since during the modify part another process might have changed an output which is than modified back during the write part. 

// Set the lines specified by the bit mask “iomask” to 1
ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_SETBITS),iomask);

// Set the lines specified by the bit mask “iomask” to 0
ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_CLRBITS),iomask);

The IO mask defines which bits are set or cleared, a 1 execute the task, a 0 is ignored. To set “a” specific address on the port would therefor require two calls, one for setting the 0’s and one for settings the 1’s. Assume a 18 bit wide port were the lower 8 are the data bus, the next 8 are the address bus, than the /WR signal and finally the /RD signal. Writing the value 0b00001111 to address 0b00110011 would than result in:

ioctl (some command to set databus to output);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_SETBITS), 0b01 00110011 00001111);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_CLRBITS), 0b01 11001100 11110000);

Since in both cases the /WR bit is set and first the SETBITS is used this will result in a faling flank on /WR when the second IO call is executed. The receiver can use this flank by connecting it to an interrupt pin and in the ISR copy the date from the address and data part (after a slight delay) and execute the command.

A read from address 0b00110011 would result in:

ioctl (some command to set databus to input);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_SETBITS), 0b10 00110011 11111111);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_CLRBITS), 0b10 11001100 00000000);

and after waiting a bit:

value=ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS));

Also here the falling flank on /RD can be used for triggering an ISR to place the data on the bus and remove it after some delay or when the /RD pin become 1 again. For this it might be smart to also set the /RD in the first call for writing a command. Also setting the direction of the databus only needs to be done when the previous command was different (read versus write).

All this brings two conclusions:

  • There is no need to map the address part in an consecutive set of pins
  • It requires two to four IO calls per command

The first conclusion is perhaps not clear, reason for this is that the command will be defined as a constant value in the application (most likely). It is not needed to take an address, split it in multiple parts and using shift functions to place the bits in the right location.

So, using OG3..OG5, IOG8..IOG15 as address lines, IOG16..IOG23 as data lines, IOG0 as /RD and OG1 as /WR would provide a 2048 possible commands using 8 bit data. That should be more than enough!

That leaves the interrupt signal, since there is no true interrupt support in the normal IO driver this might require a custom device driver. All input pins can be used as a interrupt pin, so IG3 will do the trick.

OG4 and OG5 can be used for driving 2 LED’s, these always prove to be handy during development and can indicate data transfer in the final application.

Finally, it would be nice to add an SD-card slot as well. This has nothing to do with the primary motor cortex but if the application becomes big or requires lots of storage for storing collected data it is good to put this on a replaceable SD-card instead of writing the internal FLASH of the FB all the time. There is a schematic of the ZigBee add-on board that also provides an SD-card. Damn! This uses port G as well: IG1, OG1, OG3 and OG4. Exactly the same pins as for my extended address lines, /WR and /INT.

But is does seem input pins are not linked to output pins when they are separately available on the FB. The data from the SD-card is read using IG1 while the clock for the card is generated using OG1. I will do a small test later to easy my mind, but for now that leaves below listed unused pins:

  • IOG0, IG2..IG5, OG5, IOG24, OG25, OG28 and OG29

After a reset the FB will set a specific direction and state to all IO pins. To prevent direction conflicts the AT90CAN will set all IO pins to input except for the /INT output. For this reason it is best to use a dedicated input pin on the FOXBoard, for example IG2. Than the connection could be:

  • /INT on IG2
  • Data 0..7 on IOG8..IOG15
  • Address 0..9 on IOG16..IOG24, OG25
  • /RD on OG28
  • /WR on OG29
  • LED on OG5

As a result: 1024 possible commands that can use 8 bits of data, read and write, interrupt and a debug LED.

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];
begin
  CANUSBOpen(”, CAN_BAUD_500K, CANUSB_ACCEPTANCE_CODE_ALL, CANUSB_ACCEPTANCE_MASK_ALL, CANUSB_FLAG_TIMESTAMP);
  CANUSBVersionInfo(@VerText[0]);
  Label1.Caption := VerText;
  BtnOpen.Enabled := False;
  BtnClose.Enabled := True;
  BtnStatus.Enabled := True;
  BtnWrite.Enabled := True;
  Timer1.Enabled := True;
end;

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);
Var
  CANMessage: CANmsg;
  DummyStr: String;
  tmp: Integer;
begin
  if (CANUSBRead(CANMessage) = ERROR_CANUSB_OK) then
   begin
     DummyStr := Format(‘ID = %x,’, [CANMessage.id]);
     DummyStr := DummyStr + Format(‘ LEN = %d, DATA = ‘, [CANMessage.len]);

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

     Label3.Caption := DummyStr;
   end
end;

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

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.

Oct 27

The CAN interface and the low level library that seems to be available in the demo code from ATMEL provide the physical layer (electrical) and the data link layer (frames) of the OSI model. As a result you can send and receive frames that contain up to 8 data bytes. What these data bytes mean is not determined, it is up to the developer to define how to use them.

During the search on CAN reference material, I found regularly the reference to CANOpen. This standard implements the network layer (variable data length), the transport layer (data segmentation), the session layer (initiate and respond) and the presentation layer (what does which byte mean).

Every CANOpen device makes internal data (process data, parameters) available on the bus via a defined interface, whereby this data is organized in an object directory. Entries in the object directory are accessed via a 16-bit index and supplemental 8-bit sub-index. The index range is subdivided into logical segments to organize the structure so that it easier to comprehend by users. The name of a device, for example, can be read from index 0x1008 (sub-Index 0).

Index (hex)    Object
0000              not used
0001-025F     Data Types
0260-0FFF     Reserved for further use
1000-1FFF     Communication Profile Area
2000-5FFF     Manufacturer Specific Profile Area
6000-9FFF     Standardized Device Profile Area
A000-AFFF     Reserved for further use

I’m not sure this is needed for my robots, but it is interesting to see what is available for use on the AT90CAN controllers and how this would work in practice.

« Previous Entries Next Entries »