CAN Bus Linux Driver
News 7-Dec-2004
Now we are tuning for efficiency.
- More refactoring.
- Finally add timestamps (kernel jiffies).
- Allow opening a second CAN device (/dev/can1), which configures message objects 1 and 2 to receive the high data rate IMU Accel and Gyro data messages. This allows a second FC thread to operate directly upon large batches of IMU messages at a time, thereby reducing unnecessary context switches. Moving IMU message receipt to the unbuffered objects is OK, since it is not disasterous to lose these, and it does preserve the remainder of the messages received. This change is very rocket specific, hard coding the IMU CAN ids into the driver.
News 5-Sept-2004
Many reliablility problems were solved:
- Use only the buffered message object 14 for reads. Adapt the read interrupt handler to work better with that object.
- Use only message object 0 for data writes and RTR sends. (All other message objects are unused.) Set the id mask to all care.
- Reset the status register for all types of interrupts, not just errors.
- Simplify the queuing logic between front and back ends of the driver.
Thank you, ?KeithPackard!
News 18-August-2004
Uncanny has been installed and tested on the launch tower and the Flight Computer! In practice, Phase 1 (interruptless) was not completed, and we moved directly into Phase 2.
The main limitation that was uncovered was the inability to detect arbitrary RTR messages. Instead, the Intel chip is designed for the user to set up message buffers with data to send automatically when the matching RTR message is received, without having to involve the higher level software. We have adapted the PIC nodes not to send RTR messages to work around this limitation.
News 5-Feb-2004
Freenix paper accepted! The paper will be refereed with a final submission deadline of March 25th. The referee is Ralf Nolden (kde.org). Now I'll have to decide whether it's worth a trip to Boston in the summer.
- Unfortunately, work intervened and I had no time to finish the paper or the driver. Also, Ralf had a family emergency and never responded.
Since the paper is supposed to be about developing a working driver, hopefully this will be a kick in the butt to get working on this more regularly. There might be a test on the LTC this weekend at Andrew's house. (In the meantime, small amounts of the interrupt handler have been written.)
News 31-Dec-2003
Freenix paper submitted! The ?LaTeX source will be attached to AbstractFreenix2004 presently.
Not much else has been done on the driver recently. It is in suitable shape to install and test on the LTC, but Ted has been working on the LTC electronics all month.
News 2-Dec-2003
Bart suggested we do a writeup of the CAN driver work for Freenix in July 2004 in Boston. The deadline for submission of an abstract is 16-Dec-2003. An outline is on AbstractFreenix2004.
The Flight Computer and ?Launch Tower Computer MOPS/520 boards contain a built-in Intel i82527 CAN interface chip. We found an open source Linux driver which handles this chip, which we modified to work on the MOPS board.
Capabilities
- Presents one device file per internal CAN I/O buffer. The device minor number selects which buffer. There are fifteen buffers to choose from. The fifteenth is read-only and has a one-element queue.
- Reads and writes fixed length messages (
struct canmsg_t
) - Buffers messages read and written to the device, with appropriate interrupt handling
- Device can be opened non-blocking
Problems
- Reads and writes cannot be mixed on the same open device, even if opened with
O_RDWR
. read()
has a non-standard implementation to deal with RTR (Request to Transmit a Response) messages. If you fill the buffer with a CAN message ID and the RTR bit set before callingread()
, it will block until the response to that particular RTR message is received. This presumes (incorrectly) that the RTR message was sent successfully by an immediately preceding call towrite()
. (At least this is the intent; the driver currently has a bug so that even this won't work.)- But... you cannot
write()
a message with the RTR bit set! (This bug is pervasive, with a lot of cruft in the driver to work around its design decisions.) select()
does not work because the driver does not implementpoll()
. This causes any use of select on a CAN device descriptor to return immediately. Code written using select will spend all its time blocking on a 3 second timeout inread()
.
CAN Driver Rewrite
The problems outlined above along with the "one device per message object" design decision were found to be too limiting. The current driver is overly general in order to deal with lots of settable parameters, two types of CAN chips, and a multitude of different boards and architectures.
The proposed driver rewrite features:
- Specific to the MOPS 520 board and i82527 chip for simplicity.
- no modparam support; all settings are hardwired
- hardwired IO address range 0x2000-0x20ff, using shared interrupt 10
- bus timing hardwired to 1Mbps, chip clock hardwired to 8MHz
- hardwired major/minor device number 91/0
- no ID filtering
- standard 11-bit IDs only; extended 27-bit IDs not supported
- Presents a single device
/dev/can
which makes full use of all 15 message objects to allow use of read, write, and RTR messages interspersed on the sameO_RDWR
descriptor.- Device will be exclusive open
- Cleaner implementation
- remove lots of layers of indirection required for hardware abstraction
- no dynamic memory allocation
- Retain
struct canmsg_t
as the data object forread/write
- NOTE fields are changing, see below
write
will write both data and RTR messagesread
will read both data and RTR response messages- NOTE: using
sucan
, we determined that only the buffered message 15 can be configured to receive and detect random RTR messages. The driver will thus always use message 15 when opened for reading CAN messages. read
will not be sensitive to the incoming data buffer
- NOTE: using
poll
implemented so thatselect
works correctly, at least on read descriptors- More consistent error codes and plenty of debug messages
Phase 0 user mode chip driver for easier experimentation [DONE 18-Nov-2003]
- Apparently, user applications can access IO ports above 0x400 in x86 Linux systems. The app is required to run as root and make system call
iopl(3)
in order to do so. One can then useinb/outb
to twiddle and read the CAN registers. (One could then also disable interrupts, but that would be a Bad Idea.) - An interactive environment would let us experiment more easily to determine the proper sequence for sending an RTR message.
- I propose a tool
sucan
that takes single letter commands to- Select message object 1-15
- Set and reset the eight flags in the message CTL registers
- Set the ID of the message
- Set the direction flag in the message CFG register (xmit/recv)
- Enter 0-8 hex data bytes into the message DAT0-7 registers and set DLC in the message CFG register accordingly
- Block waiting to receive a message or finish transmitting a message (w/timeout)
- The tool would do standard chip initialization on startup
- No CAN interrupts enabled!
- The tool would display the state of the current message object after each command.
Phase 1 (started 11 Nov 2003, suitable for low bandwidth commands to LTC):
- New project, Linux device infrastructure (mostly copied from old driver) [DONE]
- From 60 down to 10 source/makefiles
- Committed to
PSAS/c/can-linux/uncanny
- MOPS/i82527 driver setup [DONE]
- TODO: update chip setup based on
sucan
experiments
- TODO: update chip setup based on
- File operations merged into
fileops.c/h
[DONE]open, close
exclusive open [DONE]read
[DONE, cannot detect RTR messages]write
[DONE]- read and write RTR implementations have been confirmed with
sucan
- Spin waiting instead of interrupt handling for simplicity [needs testing]
- poll message registers directly for their status (inefficient, but simple)
- [TODO] timeouts?
- Use the 15 on-chip message objects for read/write/RTR buffering [needs testing]
- reserve some messages (5?) for reading
- Modification of ltc-fc-common library, ltc service as needed [DONE]
- NOTE I am changing the exported
canmsg_t
incan.h
to be closer to the SJA form - Replace seperate
id, rtr, len
fields with one combinedid
field, same as on the PICs which should allow sharing more headers between firmware and FC level software. - Macros
CAN_ID, CAN_RTR, CAN_LEN
to extract info from acanmsg_t
- Macro
MAKE_CAN_ID
to combine 11-bit ID with RTR and data length - [TODO] adapt unit test app for the new driver
- [DONE] adapt
ltc-fc-common
library to use the new type definition - I don't know if anyone noticed, but the old driver had absolutely no support for the
timestamp
field ofcanmsg_t
. Does anyone need this field to cross the CAN bus?
- NOTE I am changing the exported
- Goal: successful transmission of single data and RTR messages [DONE]
- Goal: successful receipt of 1 Hz data messages and single RTR responses [DONE]
- Intel chip cannot detect arbitrary RTR messages
- Target completion: 9 Dec 2003
- Mostly written and linking in one evening. Simplification is good!
Phase 2 (suitable for high bandwidth telemetry from FC):
- Interrupt handler
- backside and frontside interrupt code [DONE].
- test throughput and reliablilty [DONE]
poll
, so thatselect
can be used [DONE]proc
file system support? (optional)- show internal performance statistics?
- In-memory read/write queues [DONE]
- Reasonable buffer overflow handling [DONE]
- Reimplementing queue &head-&tail with &head-count makes overflow detection easier. This has been seperately unit tested.
- Goal: successful send/receive of 100(?) Hz data messages [DONE]
- Interspersed reads/writes
- Goal: multiple outstanding RTR requests
- Completed: Sept 5, 2004
-- IanOsgood - Sept 5, 2004
Other useful pages
- Our CVS directory for the driver source
i82527.c:
lowest level interaction with the chipi82527.h:
chip specific constants and functionsirq.c:
interrupt handlers (functionsi82527_irq_*
)fileops.c:
handlers foropen(), close(), read(), write(), poll()
syscallsmain.c:
module infrastructure and driver initializationcan.h:
the definition ofstruct canmsg_t
- Higher level library to send and receive messages on the CAN bus
- uses the
FIFO_MSG
data type (must beFMT_CAN
) can_common.h, can_read.c, can_write.c, can_open.c, can_close.c
- uses the
- CanBusLinks has some general links about the CAN protocol
- CanBusIDs lists the structure we chose for our CAN message IDs.
- Specific IDs used on the rocket and launch tower are found in the CVS repository.
- CanBusUtilization talks about the CAN bandwidth requirements on the rocket
- FlightComputerBoard has a large section devoted to setting bus timing for the i82527
- DevelopmentEnvironmentForLv2 has information about how to set up your system to develop the CAN driver
- A primer for developing Linux kernal modules (PDF)
- Knowledgable folk: ?JamesPerkins, ?JameySharp, IanOsgood, BartMassey, ?KeithPackard
Chip references
- http://psas.pdx.edu/view/WEB/FlightComputer/Intel 82527 Architecture.pdf
- http://psas.pdx.edu/view/WEB/FlightComputer/Intel 82527 CAN Controller.pdf
-- IanOsgood - 03 Oct 2003