RTEMS USB Status

141 views
Skip to first unread message

Joel Sherrill

unread,
Oct 28, 2009, 1:58:03 PM10/28/09
to roset...@googlegroups.com, Sebastian Huber, Thomas Dörfler
Hi,

I am just cutting and pasting this report from Sebastian Huber and
cc'ing him. Hopefully he will be joining the group shortly. Based upon
this, I think the FreeBSD USB stack is actually a known quantity and
has a nearly finished port to RTEMS. The Minix people want this
and Sebastian has tried to do a good job of keeping a box around
the code copied in.

Sebastian also mentions a couple of other smaller efforts. The
ones I mentioned are Till's libbsdport and Sebastian's USB work.
As he mentions, we are concerned about merging BSD work
from multiple variants and it does concern us.

Enough from me... I yield the floor to Sebastian:

=====================================================Hi,

this is a short USB port report and some thoughts about BSD.

How to deal with BSD?

Currently we have four independent projects that try to use parts of the BSD
community. Xu Ray works with the USB stack from NetBSD. Andrew Sporner wants
to update the TCP/IP stack with the one in FreeBSD 7.1. Embedded brains works
with the USB stack from the current development FreeBSD. Till Straumann
developed the libbsdport.

There are different ways to port subsystems from FreeBSD to RTEMS. You can
replace locking and synchronization primitives from FreeBSD with dummy
functionality or provide a mapping to the RTEMS directives.

The current FreeBSD is capable to run on a SMP machine. If you run the FreeBSD
kernel within different RTEMS tasks this is like running FreeBSD on a SMP
machine. Thus if you provide a proper mapping of the locking and
synchronization primitives of FreeBSD to RTEMS you can use FreeBSD code without
much modification. The current TCP/IP port uses a different approach. It
introduces a giant lock outside the FreeBSD kernel and ensures that the FreeBSD
kernel will be executed through defined entry and exit points which are
protected by this giant lock.

With the current SMP aware FreeBSD system it is possible to avoid the
introduction of external giant locks and use only the native FreeBSD locking
and synchronization means. This requires that RTEMS provides some core APIs
from FreeBSD. The work with the USB stack from current FreeBSD showed that the
following APIs are important. You can obtain a man page for each API at

http://www.freebsd.org/cgi/man.cgi?query=signal&apropos=0&sektion=9&manpath=FreeBSD+8-current&format=html

Each name matches the man page entry. A proposed implementation with RTEMS
directives is given.

sx (Shared/exclusive locks):
Binary semaphores (this neglects the ability to allow shared access).

mutex (Mutual exclusion):
Binary semaphores (not recursive mutexes are not supported this way).

condvar (Condition variables):
POSIX condition variables with modifications (hack).

callout (Timer functions):
Timer server.

kthread, kproc (Tasks):
Tasks.

devfs (Device file system):
Dummy, IMFS or new implementation.

psignal (Signals):
TBD.

poll, select:
TBD.

rman (Resource management):
TBD.

devclass, device, driver, make_dev (Device management):
Use FreeBSD implementation as far as possible. FreeBSD has a nice API
for dynamic device handling. It may be interesting for RTEMS to use
this API internally in the future.

bus_space, bus_dma (Bus and DMA access):
Likely BSP dependent. A default implementation for memory mapped
linear access is easy to provide. The current heap implementation
supports all properties demanded by bus_dma (including the boundary
constraint).

Interrupt handlers can use some kind of blocking calls in FreeBSD. We can use
an interrupt handler server for this purpose.

The current USB port is based on the trunk of FreeBSD (revision 198535). The
plan is to use the stable version 8 branch for import into RTEMS.

All files for the USB port are generated through a Python script (attached
file) from modified FreeBSD sources. The generated files are placed into an
own directory hierarchy. The script changes include paths and adds a special
RTEMS configuration include file to the top of the include list. The header
guards are also modfied. The modifications done by the script are reversible.
All modifications of the original FreeBSD sources are within preprocessor
sections guarded by the __rtems__ define. So you can update with a low chance
for conflicts. This is useful for synchronization with the FreeBSD
development. Suppose we used revision X for our USB port and want to
synchronize with revision Y. We can do this in the following steps:

1. Check-out FreeBSD at revision X.
2. Make the changes done for revision X (through a script).
3. Update to revision Y.
4. Resolve conflicts.
5. Use script to generate USB port.

The FreeBSD kernel is not designed to be a library. It is incorporated as a
bunch of object files. The linker generates so called linker sets of special
objects. At runtime these sets are evaluated for example to do the system
startup. We cannot use this method instead we have to use for example an
explicit table instead of the linker set to resolve all dependencies.

The attached Python script contains a list of all FreeBSD files used for the
USB port.

TODO:

o Tests for FreeBSD API implementations.
o RTEMS is currently not able to cope with disk device removal. Some unmount()
and LibBlock changes are required for this.

CU

-- Sebastian Huber, embedded brains GmbH Address : Obere Lagerstr. 30,
D-82178 Puchheim, Germany Phone : +49 89 18 90 80 79-6 Fax : +49 89 18
90 80 79-9 E-Mail : sebasti...@embedded-brains.de PGP : Public
key available on request. Diese Nachricht ist keine geschäftliche
Mitteilung im Sinne des EHUG.

#
# Copyright (c) 2009
# embedded brains GmbH
# Obere Lagerstr. 30
# D-82178 Puchheim
# Germany
# <rt...@embedded-brains.de>
#
# The license and distribution terms for this file may be
# found in the file LICENSE in this distribution or at
# http://www.rtems.com/license/LICENSE.
#

import shutil
import os
import re

OUTPUT_DIRECTORY = 'rtems-freebsd'

BSP = '/opt/rtems-4.10/arm-rtems4.10/lpc24xx_ncs_ram'

def installHeaderFile(src):
dst = OUTPUT_DIRECTORY + '/include/rtems/bsd2/' + src.replace('rtems/', '')
try:
os.makedirs(os.path.dirname(dst))
except OSError:
pass
data = open(src).read()
out = open(dst, 'w')
if src.find('rtems') == -1:
data = re.sub('#include <', '#include <rtems/bsd2/', data)
data = re.sub('#include "([^"]*)"', '#include <rtems/bsd2/local/\\1>', data)
data = re.sub('_H_', '_HH_', data)
out.write(data)
out.close()

def installSourceFile(src):
dst = OUTPUT_DIRECTORY + '/' + src
try:
os.makedirs(os.path.dirname(dst))
except OSError:
pass
data = open(src).read()
out = open(dst, 'w')
if src.find('rtems') == -1:
data = re.sub('#include <', '#include <rtems/bsd2/', data)
data = re.sub('#include "([^"]*)"', '#include <rtems/bsd2/local/\\1>', data)
data = re.sub('_H_', '_HH_', data)
out.write('#include <rtems/bsd2/machine/config.h>\n\n')
out.write(data)
out.close()

class ModuleManager:
def __init__(self):
self.modules = []

def addModule(self, module):
self.modules.append(module)

def copyFiles(self):
try:
shutil.rmtree(OUTPUT_DIRECTORY)
except OSError:
pass
for m in self.modules:
for f in m.headerFiles:
installHeaderFile(f)
for f in m.sourceFiles:
installSourceFile(f)

def createMakefile(self):
data = 'PROJECT_RELEASE = ' + BSP + '\n' \
'include $(PROJECT_RELEASE)/Makefile.inc\n' \
'include $(RTEMS_CUSTOM)\n' \
'include $(PROJECT_ROOT)/make/leaf.cfg\n' \
'HEADER ='
for m in self.modules:
for f in m.headerFiles:
data += ' \\\n\t' + 'rtems/bsd2/' + f.replace('rtems/', '')
data += '\n'
data += 'SOURCE ='
for m in self.modules:
for f in m.sourceFiles:
data += ' \\\n\t' + f
data += '\n' \
'%.o: %.c\n' \
'\t$(COMPILE.c) -Iinclude $< -o $@\n' \
'OBJECTS = $(SOURCE:%.c=%.o)\n' \
'all: $(OBJECTS)\n' \
'\t$(AR) rcu libbsd.a $(OBJECTS)\n' \
'\t$(LINK.c) $(OBJECTS)\n' \
'install: libbsd.a\n' \
'\tinstall -c -m 644 libbsd.a ' + BSP + '/lib\n' \
'clean:\n' \
'\trm -f libbsd.a $(OBJECTS)\n'
out = open(OUTPUT_DIRECTORY + '/Makefile', 'w')
out.write(data)
out.close()

class Module:
def __init__(self, name):
self.name = name
self.headerFiles = []
self.sourceFiles = []
self.dependencies = []

def addHeaderFiles(self, files):
self.headerFiles.extend(files)

def addSourceFiles(self, files):
self.sourceFiles.extend(files)

def addDependency(self, dep):
self.dependencies.append(dep)

mm = ModuleManager()

rtems = Module('rtems')
rtems.addHeaderFiles(
[
'rtems/machine/atomic.h',
'rtems/machine/bus.h',
'rtems/machine/bus_dma.h',
'rtems/machine/config.h',
'rtems/machine/cpufunc.h',
'rtems/machine/endian.h',
'rtems/machine/_limits.h',
'rtems/machine/_align.h',
'rtems/machine/mutex.h',
'rtems/machine/param.h',
'rtems/machine/pcpu.h',
'rtems/machine/proc.h',
'rtems/machine/resource.h',
'rtems/machine/runq.h',
'rtems/machine/signal.h',
'rtems/machine/stdarg.h',
'rtems/machine/_stdint.h',
'rtems/machine/_types.h',
'rtems/machine/ucontext.h',
'rtems/machine/symbol-rename.h',
'rtems/machine/vm.h',
]
)
rtems.addSourceFiles(
[
'rtems/rtems-bsd-sysinit.c',
'rtems/rtems-bsd-nexus.c',
'rtems/rtems-bsd-autoconf.c',
'rtems/rtems-bsd-init.c',
'rtems/rtems-bsd-devfs.c',
'rtems/rtems-bsd-mutex.c',
'rtems/rtems-bsd-thread.c',
'rtems/rtems-bsd-resource.c',
'rtems/rtems-bsd-condvar.c',
'rtems/rtems-bsd-sx.c',
'rtems/rtems-bsd-select.c',
'rtems/rtems-bsd-signal.c',
'rtems/rtems-bsd-callout.c',
'rtems/rtems-bsd-misc.c',
'rtems/rtems-bsd-bus-dma.c',
]
)

local = Module('local')
local.addHeaderFiles(
[
'local/opt_bus.h',
'local/opt_cam.h',
'local/opt_ddb.h',
'local/opt_usb.h',
'local/opt_printf.h',
'local/opt_compat.h',
'local/opt_scsi.h',
'local/usb_if.h',
'local/bus_if.h',
'local/device_if.h',
'local/usbdevs_data.h',
'local/usbdevs.h',
'local/vnode_if.h',
'local/vnode_if_newproto.h',
'local/vnode_if_typedef.h',
]
)
local.addSourceFiles(
[
'local/usb_if.c',
'local/bus_if.c',
'local/device_if.c',
]
)

devUsb = Module('dev_usb')
devUsb.addHeaderFiles(
[
'dev/usb/ufm_ioctl.h',
'dev/usb/usb_busdma.h',
'dev/usb/usb_bus.h',
'dev/usb/usb_cdc.h',
'dev/usb/usb_controller.h',
'dev/usb/usb_core.h',
'dev/usb/usb_debug.h',
'dev/usb/usb_dev.h',
'dev/usb/usb_device.h',
'dev/usb/usbdi.h',
'dev/usb/usbdi_util.h',
'dev/usb/usb_dynamic.h',
'dev/usb/usb_endian.h',
'dev/usb/usb_freebsd.h',
'dev/usb/usb_generic.h',
'dev/usb/usb.h',
'dev/usb/usbhid.h',
'dev/usb/usb_hub.h',
'dev/usb/usb_ioctl.h',
'dev/usb/usb_mbuf.h',
'dev/usb/usb_msctest.h',
'dev/usb/usb_process.h',
'dev/usb/usb_request.h',
'dev/usb/usb_transfer.h',
'dev/usb/usb_util.h',
]
)
devUsb.addSourceFiles(
[
'dev/usb/usb_busdma.c',
'dev/usb/usb_core.c',
'dev/usb/usb_debug.c',
'dev/usb/usb_dev.c',
'dev/usb/usb_device.c',
'dev/usb/usb_dynamic.c',
'dev/usb/usb_error.c',
'dev/usb/usb_generic.c',
'dev/usb/usb_handle_request.c',
'dev/usb/usb_hid.c',
'dev/usb/usb_hub.c',
'dev/usb/usb_lookup.c',
'dev/usb/usb_mbuf.c',
'dev/usb/usb_msctest.c',
'dev/usb/usb_parse.c',
'dev/usb/usb_process.c',
'dev/usb/usb_request.c',
'dev/usb/usb_transfer.c',
'dev/usb/usb_util.c',
]
)

devUsbAddOn = Module('dev_usb_add_on')
devUsbAddOn.addHeaderFiles(
[
'dev/usb/usb_pci.h',
'dev/usb/usb_compat_linux.h',
]
)
devUsbAddOn.addSourceFiles(
[
'dev/usb/usb_compat_linux.c',
]
)

devUsbBluetooth = Module('dev_usb_bluetooth')
devUsbBluetooth.addDependency(devUsb)
devUsbBluetooth.addHeaderFiles(
[
'dev/usb/bluetooth/ng_ubt_var.h',
]
)
devUsbBluetooth.addSourceFiles(
[
'dev/usb/bluetooth/ng_ubt.c',
'dev/usb/bluetooth/ubtbcmfw.c',
]
)

devUsbController = Module('dev_usb_controller')
devUsbController.addDependency(devUsb)
devUsbController.addHeaderFiles(
[
'dev/usb/controller/ohci.h',
'dev/usb/controller/ohcireg.h',
]
)
devUsbController.addSourceFiles(
[
'dev/usb/controller/ohci.c',
'dev/usb/controller/usb_controller.c',
]
)

devUsbControllerAddOn = Module('dev_usb_controller_add_on')
devUsbControllerAddOn.addDependency(devUsb)
devUsbControllerAddOn.addHeaderFiles(
[
'dev/usb/controller/at91dci.h',
'dev/usb/controller/atmegadci.h',
'dev/usb/controller/musb_otg.h',
'dev/usb/controller/uss820dci.h',
]
)
devUsbControllerAddOn.addSourceFiles(
[
'dev/usb/controller/at91dci_atmelarm.c',
'dev/usb/controller/at91dci.c',
'dev/usb/controller/atmegadci_atmelarm.c',
'dev/usb/controller/atmegadci.c',
'dev/usb/controller/ehci_ixp4xx.c',
'dev/usb/controller/ehci_pci.c',
'dev/usb/controller/musb_otg.c',
'dev/usb/controller/ehci_mbus.c',
'dev/usb/controller/musb_otg_atmelarm.c',
'dev/usb/controller/ohci_atmelarm.c',
'dev/usb/controller/ohci_pci.c',
'dev/usb/controller/uhci_pci.c',
'dev/usb/controller/uss820dci_atmelarm.c',
'dev/usb/controller/uss820dci.c',
]
)

devUsbInput = Module('dev_usb_input')
devUsbInput.addDependency(devUsb)
devUsbInput.addHeaderFiles(
[
'dev/usb/input/usb_rdesc.h',
]
)
devUsbInput.addSourceFiles(
[
'dev/usb/input/uhid.c',
'dev/usb/input/ukbd.c',
]
)

devUsbInputMouse = Module('dev_usb_mouse')
devUsbInputMouse.addDependency(devUsb)
devUsbInputMouse.addHeaderFiles(
[
'sys/tty.h',
'sys/mouse.h',
'sys/termios.h',
'sys/ttyqueue.h',
'sys/ttydefaults.h',
'sys/ttydisc.h',
'sys/ttydevsw.h',
'sys/ttyhook.h',
]
)
devUsbInputMouse.addSourceFiles(
[
'dev/usb/input/ums.c',
]
)

devUsbMisc = Module('dev_usb_misc')
devUsbMisc.addDependency(devUsb)
devUsbMisc.addHeaderFiles(
[
'dev/usb/misc/udbp.h',
]
)
devUsbMisc.addSourceFiles(
[
'dev/usb/misc/udbp.c',
'dev/usb/misc/ufm.c',
]
)

devUsbNet = Module('dev_usb_net')
devUsbNet.addDependency(devUsb)
devUsbNet.addHeaderFiles(
[
'dev/usb/net/if_auereg.h',
'dev/usb/net/if_axereg.h',
'dev/usb/net/if_cdcereg.h',
'dev/usb/net/if_cuereg.h',
'dev/usb/net/if_kuefw.h',
'dev/usb/net/if_kuereg.h',
'dev/usb/net/if_ruereg.h',
'dev/usb/net/if_udavreg.h',
'dev/usb/net/usb_ethernet.h',
]
)
devUsbNet.addSourceFiles(
[
'dev/usb/net/if_aue.c',
'dev/usb/net/if_axe.c',
'dev/usb/net/if_cdce.c',
'dev/usb/net/if_cue.c',
'dev/usb/net/if_kue.c',
'dev/usb/net/if_rue.c',
'dev/usb/net/if_udav.c',
'dev/usb/net/usb_ethernet.c',
]
)

devUsbQuirk = Module('dev_usb_quirk')
devUsbQuirk.addDependency(devUsb)
devUsbQuirk.addHeaderFiles(
[
'dev/usb/quirk/usb_quirk.h',
]
)
devUsbQuirk.addSourceFiles(
[
'dev/usb/quirk/usb_quirk.c',
]
)

devUsbSerial = Module('dev_usb_serial')
devUsbSerial.addDependency(devUsb)
devUsbSerial.addHeaderFiles(
[
'dev/usb/serial/uftdi_reg.h',
'dev/usb/serial/usb_serial.h',
]
)
devUsbSerial.addSourceFiles(
[
'dev/usb/serial/u3g.c',
'dev/usb/serial/uark.c',
'dev/usb/serial/ubsa.c',
'dev/usb/serial/ubser.c',
'dev/usb/serial/uchcom.c',
'dev/usb/serial/ucycom.c',
'dev/usb/serial/ufoma.c',
'dev/usb/serial/uftdi.c',
'dev/usb/serial/ugensa.c',
'dev/usb/serial/uipaq.c',
'dev/usb/serial/ulpt.c',
'dev/usb/serial/umct.c',
'dev/usb/serial/umodem.c',
'dev/usb/serial/umoscom.c',
'dev/usb/serial/uplcom.c',
'dev/usb/serial/usb_serial.c',
'dev/usb/serial/uslcom.c',
'dev/usb/serial/uvisor.c',
'dev/usb/serial/uvscom.c',
]
)

devUsbStorage = Module('dev_usb_storage')
devUsbStorage.addDependency(devUsb)
devUsbStorage.addSourceFiles(
[
'dev/usb/storage/umass.c',
]
)

devUsbStorageAddOn = Module('dev_usb_storage_add_on')
devUsbStorageAddOn.addDependency(devUsb)
devUsbStorageAddOn.addHeaderFiles(
[
'dev/usb/storage/rio500_usb.h',
]
)
devUsbStorageAddOn.addSourceFiles(
[
'dev/usb/storage/urio.c',
'dev/usb/storage/ustorage_fs.c',
]
)

devUsbTemplate = Module('dev_usb_template')
devUsbTemplate.addDependency(devUsb)
devUsbTemplate.addHeaderFiles(
[
'dev/usb/template/usb_template.h',
]
)
devUsbTemplate.addSourceFiles(
[
'dev/usb/template/usb_template.c',
'dev/usb/template/usb_template_cdce.c',
'dev/usb/template/usb_template_msc.c',
'dev/usb/template/usb_template_mtp.c',
]
)

devUsbWlan = Module('dev_usb_wlan')
devUsbWlan.addDependency(devUsb)
devUsbWlan.addHeaderFiles(
[
'dev/usb/wlan/if_rumfw.h',
'dev/usb/wlan/if_rumreg.h',
'dev/usb/wlan/if_rumvar.h',
'dev/usb/wlan/if_uathreg.h',
'dev/usb/wlan/if_uathvar.h',
'dev/usb/wlan/if_upgtvar.h',
'dev/usb/wlan/if_uralreg.h',
'dev/usb/wlan/if_uralvar.h',
'dev/usb/wlan/if_zydfw.h',
'dev/usb/wlan/if_zydreg.h',
]
)
devUsbWlan.addSourceFiles(
[
'dev/usb/wlan/if_rum.c',
'dev/usb/wlan/if_uath.c',
'dev/usb/wlan/if_upgt.c',
'dev/usb/wlan/if_ural.c',
'dev/usb/wlan/if_zyd.c',
]
)

devPci = Module('dev_pci')
devPci.addHeaderFiles(
[
'dev/pci/pcireg.h',
'dev/pci/pcivar.h',
]
)

devUsbBase = Module('dev_usb_base')
devUsbBase.addHeaderFiles(
[
'bsm/audit.h',
'sys/acl.h',
'sys/bufobj.h',
'sys/_bus_dma.h',
'sys/bus_dma.h',
'sys/bus.h',
'sys/callout.h',
'sys/cdefs.h',
'sys/condvar.h',
'sys/conf.h',
'sys/ctype.h',
'sys/endian.h',
'sys/errno.h',
'sys/event.h',
'sys/eventhandler.h',
'sys/fcntl.h',
'sys/filedesc.h',
'sys/file.h',
'sys/filio.h',
'sys/ioccom.h',
'sys/_iovec.h',
'sys/kernel.h',
'sys/kobj.h',
'sys/kthread.h',
'sys/ktr.h',
'sys/libkern.h',
'sys/limits.h',
'sys/linker_set.h',
'sys/_lock.h',
'sys/lock.h',
'sys/_lockmgr.h',
'sys/lockmgr.h',
'sys/lock_profile.h',
'sys/lockstat.h',
'sys/mac.h',
'sys/malloc.h',
'sys/mbuf.h',
'sys/module.h',
'sys/mount.h',
'sys/_mutex.h',
'sys/mutex.h',
'sys/_null.h',
'sys/osd.h',
'sys/param.h',
'sys/pcpu.h',
'sys/poll.h',
'sys/priority.h',
'sys/priv.h',
'sys/proc.h',
'sys/_pthreadtypes.h',
'sys/queue.h',
'sys/refcount.h',
'sys/resource.h',
'sys/rtprio.h',
'sys/runq.h',
'sys/_rwlock.h',
'sys/sched.h',
'sys/select.h',
'sys/selinfo.h',
'sys/sigio.h',
'sys/signal.h',
'sys/signalvar.h',
'sys/_sigset.h',
'sys/_sockaddr_storage.h',
'sys/socket.h',
'sys/stddef.h',
'sys/stdint.h',
'sys/_sx.h',
'sys/sx.h',
'sys/syscallsubr.h',
'sys/sysctl.h',
'sys/syslimits.h',
'sys/systm.h',
'sys/time.h',
'sys/timespec.h',
'sys/_timeval.h',
'sys/ttycom.h',
'sys/_types.h',
'sys/types.h',
'sys/ucontext.h',
'sys/ucred.h',
'sys/uio.h',
'sys/unistd.h',
'sys/vmmeter.h',
'sys/vnode.h',
'sys/rman.h',
'sys/reboot.h',
'sys/bitstring.h',
'sys/linker.h',
'vm/uma.h',
'vm/vm.h',
'fs/devfs/devfs_int.h',
]
)
devUsbBase.addSourceFiles(
[
'kern/kern_linker.c',
'kern/init_main.c',
'kern/kern_conf.c',
'kern/kern_module.c',
'kern/subr_bus.c',
'kern/subr_eventhandler.c',
'kern/subr_kobj.c',
'kern/subr_prf.c',
'kern/subr_rman.c',
'kern/subr_unit.c',
'libkern/bcd.c',
]
)

cam = Module('cam')
cam.addHeaderFiles(
[
'sys/ata.h',
'cam/cam.h',
'cam/cam_ccb.h',
'cam/cam_sim.h',
'cam/cam_xpt_sim.h',
'cam/scsi/scsi_all.h',
'cam/scsi/scsi_da.h',
'cam/ata/ata_all.h',
'cam/cam_periph.h',
'cam/cam_debug.h',
'cam/cam_xpt.h',
'cam/cam_queue.h',
]
)
cam.addSourceFiles(
[
'cam/cam.c',
'cam/scsi/scsi_all.c',
]
)

mm.addModule(cam)
mm.addModule(devUsbStorage)

mm.addModule(rtems)
mm.addModule(local)
mm.addModule(devUsbBase)
mm.addModule(devUsb)
mm.addModule(devUsbQuirk)
mm.addModule(devUsbController)
mm.addModule(devUsbInputMouse)

mm.copyFiles()
mm.createMakefile()

Reply all
Reply to author
Forward
0 new messages