| com-1274 (How to run it on Linux-2.6) |
“Com-1270” by Eurotech is a PC/104 board with 8 serial ports, 2 CAN
interfaces and a 10Mbit RTL8019 Ethernet port. It has been replaced by
“Com-1274”, distributed by both Eurotech and Parvus
(parvus.com) which has 8 serial ports and two CAN interfaces,
without Ethernet (which is now on most mother boards, at 100Mbit).
This document explains how to run com-1274 and com-1270, the latter only as far as the multi-serial port and CAN interfaces are concerned.
The information in this document has been gathered on a “CompuLab
CM-iGLX” motherboard, contributed by Evan V. Hansen of
3d-p.com, who also donated the 1274 board and sponsored the
associated work, allowing the public release of this documentation.
Any opinions expressed here, however, are only my own, and don't necessarily reflect the ones of any person of company referenced here.
The kernel versions used here are 2.6.24 and 2.6.36, in their vanilla flavors.
The 1274, like the 1270, features configurable addresses and interrupt lines, but configuration must be performed in DoS (which used to stand for “disk operating system” but this millennium is definitely “denial of service”).
We'd love the manufacturer to release information about the configuration protocol to do that directly in GNU/Linux, but this hasn't happened, yet – well, on request they release their ASM source files, but turning them to useful code in a sane environment would really take too much.
To configure under DOS, you could run dosemu with the released
freedos image. What I've done is changing the configuration
file to open access to a number of I/O ports with this line (it's
a single line in /etc/dosemu/dosemu.conf):
$_ports = "range 0x110,0x1a0 range 0x280,0x2c0 0x80 0x1e0
0x300 0x30a 0x213 0xa79 range 0x99,0x9c"
With this in place, run dosemu -s and run their
setup.exe. (The ports listed above have been identified by
looking at the log file of dosemu after activating debugging for
I/O accesses: -D+i).
Whether or not the address ranges and interrupts work with your own
motherboard is a roll of dice as usual. This document assumes you have
found the working parameters using some black magic, possibly sending
arcane commands to your PCI-to-ISA bridge in order to open access to
the relevant areas. Or you may need to configure other chips like the
“South Bridge” or “Companion Chip”. This document is not concerned
about those steps, even though they are usually the most
time-consuming. You may want to use msr.ko (see Other Tools) to this aim.
To boot 2.6.24 on the embedded system I used for x86 development
I used the configuration found as configs/2.6.24-iGLX.config
(this configuration includes the CAN modules as well).
The following points proved important in my specific case:
CONFIG_SERIAL_8250_PNPCONFIG_EMBEDDED and then
disable CONFIG_PNP.
SERIAL_8250_NR_UARTSCONFIG_SERIAL_8250_RUNTIME_UARTSSERIAL_8250_EXTENDEDSERIAL_8250_SHARE_IRQSERIAL_8250_EXAR_ST16C554CONFIG_ISA and
CONFIG_SERIAL_8250_MANY_PORTS (the former is mandatory,
the latter is not).
SERIAL_8250_DETECT_IRQMoreover, please note that I haven't been able to compile with
gcc-4.3, as the system was reporting a kernel panic at boot time,
for a division by zero within update_wall_time.
Being unable to find the bug, I finally installed gcc-4.1 (there is a Debian package in etch) and compiled with the following command:
make CC=gcc-4.1
To boot 2.6.36 I used the configuration found in this package as
configs/2.6.36-iGLX.config which includes the can modules,
like the 2.6.24 configuration described earlier.
The following points proved important in my
specific case:
CONFIG_SERIAL_8250_PNPCONFIG_EMBEDDED but you don't need to add CONFIG_ISA.
SERIAL_8250_NR_UARTSCONFIG_SERIAL_8250_RUNTIME_UARTSSERIAL_8250_EXTENDEDSERIAL_8250_EXAR_ST16C554CONFIG_ISA and CONFIG_SERIAL_8250_MANY_PORTS
set.
SERIAL_8250_SHARE_IRQSERIAL_8250_DETECT_IRQUnlike with 2.6.24, no specific compiler choice is needed at this time, as far as I know.
The ports are standard 16550 UART devices mapped in the I/O space. The only peculiar feature is that the interrupt line is shared among them. There is a special I/O port that acts as a multiplexer, so you can look there in order to avoid polling all ports for an interrupt condition.
What is described here applies to both 2.6.24, 2.6.36 amd 2/6/38-rc2. Here we'll assume the following configuration for I/O addresses:
0x2800x2880x2900x2980x2a00x2a80x2b00x2b80x2c0You can configure all the ports as ttyS ports using the
standard 8250/16550 device driver. To do that you need to load the a
module that registers the ports, which is included in this package, in
the directory modules. The module receives the following
parameter on the command line:
addrstatus_addrirqTo compile the module, enter ./modules/ in this package, set the
LINUX environment variable to point to your own Linux sources
and run make. If you installed the header package to develop
external headers, you can point LINUX to that directory,
instead of the complete source tree.
After compilation, you'll have uart-127x.ko, which you need to load
on your target system, with a command similar to:
insmod uart-127x.ko irq=5
If you forget to pass the irq= argument, you'll get EINVAL.
What I get back in insmod is this:
serial8250.6: ttyS4 at I/O 0x280 (irq = 5) is a 16550A
serial8250.6: ttyS5 at I/O 0x288 (irq = 5) is a 16550A
serial8250.6: ttyS6 at I/O 0x290 (irq = 5) is a 16550A
serial8250.6: ttyS7 at I/O 0x298 (irq = 5) is a 16550A
serial8250.6: ttyS8 at I/O 0x2a0 (irq = 5) is a 16550A
serial8250.6: ttyS9 at I/O 0x2a8 (irq = 5) is a 16550A
serial8250.6: ttyS10 at I/O 0x2b0 (irq = 5) is a 16550A
serial8250.6: ttyS11 at I/O 0x2b8 (irq = 5) is a 16550A
and the ports are all properly working. The fast way to test them is
using stty, cat and echo with I/O redirection after looping
back one UART to another. However, you must remember to remove echoing
or you'll get in trouble (stty -echo -F /dev/ttySx).
Please note that removing the module is not fully supported; the problem is not in the module itself but in the 8250 core driver. On unload you will get this message on the console:
Device 'serial8250.6' does not have a release() function,
it is broken and must be fixed.
WARNING: at drivers/base/core.c:107 device_release()
In order to run the socketcan device drivers on 2.6.24, I had to back-port the CAN patches from more recent kernels, as well as add the old drivers from an svn checkout of the socketcan project.
I cherry-picked or generated these patches in my git tree, and then saved with “git format-patch” into patches/2.6.24 in this package. The patch list is the following:
0001-Makefile-added-libgcc.patch
0002--CAN-Allocate-protocol-numbers-for-PF_CAN.patch
0003--CAN-Add-PF_CAN-core-module.patch
0004--CAN-Add-raw-protocol.patch
0005--CAN-Add-broadcast-manager-bcm-protocol.patch
0006--CAN-Add-virtual-CAN-netdevice-driver.patch
0007--CAN-Fix-plain-integer-definitions-in-userspace-he.patch
0008--CAN-Add-missing-Kbuild-entries.patch
0009--CAN-Clean-up-module-auto-loading.patch
0010--CAN-Move-proto_-un-register-out-of-spin-locked.patch
0011--CAN-Minor-clean-ups.patch
0012--CAN-Add-documentation.patch
0013--CAN-Update-documentation-of-struct-sockaddr_can.patch
0014-CAN-use-hrtimers-in-can-bcm-protocol.patch
0015-can-Fix-copy_from_user-results-interpretation.patch
0016-can-Fix-can_send-handling-on-dev_queue_xmit-fai.patch
0017-can-add-sanity-checks.patch
0018-can-Add-documentation-for-virtual-CAN-driver-usage.patch
0019-can-Fix-CAN_-EFF-RTR-_FLAG-handling-in-can_filter.patch
0020-can-omit-received-RTR-frames-for-single-ID-filter-l.patch
0021-socketcan-copied-drivers-net-can-old-and-include-so.patch
0022-socketcan-added-i82527-kconfig-and-makefile.patch
0023-socketcan-add-sja1000-directory-to-obj-m.patch
The role of the patches is as follows:
0001-Makefile-added-libgcc.patchlibgcc.a to the link, or version 2.6.24
won't compile with current compilers (undefined symbols
__umoddi3 and __udivdi3). The problem was fixed
after 2.6.24.4, but you can apply this set to 2.6.24.6
or later anyways, as the correct fix is orthogonal to this hack.
0002 .. 00202.6.25-rc1, other patches come
from later versions, up to 2.6.28.
0021-socketcan-copied-drivers-net-can0022 .. 0023com1274 board, but I have a motherboard
with an SJA1000, so I added both.
You can apply with either patch -p1 or git am, as you prefer.
With these in places, you can activate the CAN modules (they are already
activated in the example configuration provided).
If you already booted what you compiled in Booting 2.6.24, you
don't need do reboot, as the patch set only adds new modules. You can
just run make oldconfig and make modules, possibly
setting CC=gcc-4.1 to match how you compiled the kernel.
The following configuration options should be set in the oldconfig
step:
CONFIG_CAN=m
CONFIG_CAN_RAW=m
CONFIG_CAN_OLD_DRIVERS=m
CONFIG_CAN_SJA1000_OLD=m
CONFIG_CAN_I82527_OLD=m
You can safely reply no to other can-related questions.
On the target board, then, you'll need to load the modules for CAN
support: can.ko and can_raw.ko.
In 2.6.36 socketcan is already part of the official kernel but the “old” 82527 is not. Therefore, I rebased the last patches for 2.6.24 listed above and fixed them to compile in 2.6.36. The same patch set works unchanged in 2.6.38-rc2 (the last one I used on my target board, at time of writing).
The patch set, saved by “git format-patch” is available in patches/2.6.36 in this package. The patch list is the following:
0001-socketcan-copied-drivers-net-can-old-and-include-so.patch
0002-can-removed-old-headers-from-previous-patch.patch
0003-socket-can-added-i82527-kconfig-and-makefile.patch
0004-socketcan-add-sja1000-directory-to-obj-m.patch
0005-fixes-for-old-i82527-can-driver.patch
0006-fixes-for-old-sja1000-can-driver.patch
The role of the patches is as follows:
0001-socketcan-copied-drivers-net-can0002-can-removed-old-headers-from-pre0003 .. 0004Kconfig and
Makefile. As above I add SJA1000 as well as I use it for
the motherboard CAN device.
0005 .. 0006With these patches in place, you can compile the CAN driver for this Eurotech/Parvus board, as described in the next section.
The driver for 82527 is not part of the upstream kernel, so I took the one from the svn repository of the socketcan project. The patches used on the previous sections add the driver to the kernel source tree, but you might prefer compile it externally, following the documentation that's part of the package. I used version 1060 of the svn repository (2009-09-18):
svn checkout svn://svn.berlios.de/socketcan/trunk -r 1060
While the version is somewhat old, it matches my need to run on 2.6.24.
After patching the kernel (see previous sections) and running
make modules, you'll find the following modules that are
relevant to CAN and our chip:
net/can/can.ko
net/can/can-raw.ko
drivers/net/can/old/i82527/i82527-pc7io.ko
drivers/net/can/old/i82527/i82527-esdio.ko
drivers/net/can/old/i82527/i82527-iomem.ko
The first two modules are the core CAN support, and must be loaded,
while the only '527 module we need is i82527-iomem.ko, as it is
the one that matches how the chip is mounted on the com1274 board.
To load the driver, we need to specify the memory addresses and interrupt numbers. For the two-port version of the 1274, with my own settings for memory address and interrupt number, I use the following command:
insmod i82527-iomem.ko base=0xc8000,0xc8100 irq=11,12 bcr=0x4c,0x4c
The bcr argument is the Bus Configuration Register, whose
correct value depends on how the hardware is mounted. The 1274 the
correct value is 0x4c.
i82527-iomem driver v0.0.4 (2007-08-03)
i82527-iomem - options [clk 16.000000 MHz] [restart_ms 100ms] [debug 0]
i82527-iomem - options [force_dmc 0] [irq_mode 1]
i82527-iomem: checking for i82527 on address 0xC8000 ...
i82527-iomem: base 0xC00C8000 / irq 11 / speed 500 / btr 0x0 / rx_probe 0 / mo15 sff
i82527-iomem: checking for i82527 on address 0xC8100 ...
i82527-iomem: base 0xC00C8100 / irq 12 / speed 500 / btr 0x0 / rx_probe 0 / mo15 sff
If you have problems in accessing I/O memory (for example for a misconfiguration in the PCI-ISA bridge) you'll get this instead:
i82527-iomem: checking for i82527 on address 0xC8000 ...
i82527-iomem: probing 0xC00C8000 failed (reset)
i82527-iomem: probably missing controller hardware
Later, when you run ifconfig can1 up (you have both can0 and
can1) you'll get the following messages:
can1: calculated best baudrate: 500000 / btr is 0x4067
can1: setting BTR0=40 BTR1=67
can1: i82527: using msg object 15 for SFF reception.
If you are new to socketcan, you may want to check my samplecan
sample application, found within tools/ in this package. I wrote
it while reading Documentation/networking/can.txt, that you may
find useful.
I always use the samplecan tool to check that my setup is working. The typical problems you may find are:
can.ko or can-raw.ko. In this case
the tool exits 1 as it receives “Address family not supported
by protocol”.
If it works, the tool sends one packet per second at default speed, and reports any packet it receives from the bus. There are a few options, like listen-only, or changing the CAN interface. Please check the sources.
While getting mad in looking for motherboard issues (mainly interrupt
routing and access to ISA memory), I wrote three kernel modules that are
under modules in this package. Both modules make a specific action
at load time and then return EAGAIN, so you can save unloading them.
I'm not proud of them, as it's all quick-and-dirty stuff, but you may find them useful.
The modules are
allirq.koNR_IRQS), reporting any failure through printk.
Each handler prints a message the first time it is invoked, and
at unload time the total number of interrupts received by each handler
is reported. I used this to check whether interrupts reached the
motherboard or not. Sure, you can put voltage on the bus wires
and look at what happens at software level.
msr.kowrite=1 (default 0:
read the register); msr= (number of register); vall=
(the low 32 bits, used for writing); valh= (the high 32
bits, used for writing). The module reports through printk
what it reads or writes. You need one insmod for each register
access, but for configuring it's enough.
remap512.kobase=. I used this to make sure that
82527 access worked fine, as /dev/mem gave unexpected results.
For the record, this gave the same results.