Disclaimer:The following are my notes. As I am learning electronics, I am making my notes available. I hope they will be of benefit. However, I do not guarantee the accuracy of my work. I recommend the reader exercise critical thinking.
|
18F USB Driver
PIC18F4550 Driver
Please review the PIC18 Setup and
PIC18 Firmware page before
reading this page.
This page will cover the creation of the driver for the REPING program
REPING: A Linux server program constructs a packet of data and sends it to the
PIC18F4550 microcontroller using USB communications.
The microcontroller reverse the order of the bytes in the packet and
send the new packet back to the server.
I call this program "reping".
OS Commands
The lsusb command shows the
devices connected to the USB bus.
The new PIC18F4550 device shows up as "Microchip Technology Inc," with and ID of 04d8:000c.
The ID portion is defined within the USB_DESCRIPTOR_DEVICE section of
the usb_descriptors.c file.
> lsusb
Bus 001 Device 011: ID 04d8:000c Microchip Technology Inc.
The text is defined later using a USB_DESCRIPTOR_STRING descriptor.
|
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
. . .
0x04D8, // Vendor ID
0x000C, // Product ID
. . .
};
|
More information about the usb device can be obtained with the the -v and the -s
options of the lsusb command.
The lsusb command identifies one interface, interface number 0, with two end points (EP).
The first EP is an OUT end point, with address 0x01
and is configured for Bulk transfer mode.
The second EP is in IN end point, with address 0x81
and is configured for Bulk transfer mode.
You can compare the lsusb output with the definitions in the usb_descriptors.c code.
lsusb -v -s 001:011 |
usb_descriptors.c |
Configuration Descriptor:
bLength 9
. . .
bNumInterfaces 1
. . .
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bNumEndpoints 2
. . .
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type none
wMaxPacketSize 64
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type none
wMaxPacketSize 64
bInterval 1
|
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
. . .
/* Interface Descriptor */
. . .
USB_DESCRIPTOR_INTERFACE,
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
0x00, // Class code
. . .
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_OUT, //EndpointAddress
_BULK, //Attributes
USBGEN_EP_SIZE,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_IN, //EndpointAddress
_BULK, //Attributes
USBGEN_EP_SIZE,0x00, //size
1 //Interval
};
|
The wMaxPacketSize corresponds to the USBGEN_EP_SIZE field.
The macro USBGEN_EP_SIZE is defined in usb_config.h with a value 64.
The Microchip USB Framework provides pre-defined values for end point addresses.
The EP used in the example firmware code is EP number 01.
However, we reference the EP by its address.
Section 9.6.6 (page 269) of the
USB 2.0 Specifications
defines an Endpoint Address as follows: Bit 7: Direction (0 = OUT, 1 = IN); Bit 6...4: Reserved, reset to zero; and Bit 3...0: The endpoint number.
|
Bit 7 |
Bit 6...4 |
Bit 3...0 |
|
|
0 = OUT / 1 = IN |
Reserved |
EP Number |
|
EP Number: 1
Type: Bulk
Direction: IN
|
1 |
000 |
0001 |
= 0x81 |
EP Number: 1
Type: Bulk
Direction: OUT
|
0 |
000 |
0001 |
= 0x01 |
|
The USB Framework file \Microchip\Include\Usb\usb_device.h defines
_EP01_OUT as 0x01 and _EP01_IN as 0x81. This seems to explain the origin
of the EP01 addresses.
LibUSB client (user-space)
This driver is written using libusb and runs in user space.
The first task of the program is to find how to reference the USB end points.
This is fairly complex. The rest of the program is devoted to sending and receiving
information from the USB device.
reping.c
Here is the command to compile this program. The program will need to be run as the root user.
wget http://www.camotruck.net/rollins/electronics/reping.c
gcc -o reping.exe reping.c -lusb
./reping.exe
Kernel Module and SYSFS
This next example is a kernel module that provides a sys filesystem interface.
This module is derived from examples provided by Greg Kroah-Hartman: usbled.c and usb-skeleton.c.
Also, the sysfs documentation by Patrick Mochel gave me a better understanding about sysfs.
I don't know all the tricks about adding kernel modules, but I found a way to add this
module to a kernel source tree. This example assumes you have the linux-2.6.18 source.
Here are the steps.
Unpack the kernel source
tar xvzf linux-2.6.18.tar.gz
Modify Kconfig
cd linux-2.6.18/drivers
Open the file Kconfig
Add the line, source "drivers/reping/Kconfig" at the end of the file, just before the endmenu tag.
Modify Makefile
cd linux-2.6.18/drivers (you should already be in this directory>
Open the file Makefile
Add the following to the end of this file:
obj-$(CONFIG_REPING) += reping/
Add the REPING kernel module code
Download the kernel module and install it into the directory linux-2.6.18/drivers .
wget http://www.camotruck.net/rollins/electronics/reping.tar.gz
tar xvzf reping.tar.gz
Now you can compile the kernel modules as usual.
cd linux-2.6.18
make oldconfig
make modules
make modules_install
To test the device, connect the USB device to the computer and insert the module.
insmod /lib/modules/2.6.18/kernel/drivers/reping/reping.ko
Navigating through the /sys filesystem, you will find the interface for the reping module.
[root@host]# ls -l /sys/bus/usb/drivers/reping
total 0
lrwxrwxrwx 1 root root 0 Jul 4 13:49 1-2:1.0 -> ../../../../devices/pci0000:0...
--w------- 1 root root 4096 Jul 4 13:50 bind
lrwxrwxrwx 1 root root 0 Jul 4 13:50 module -> ../../../../module/reping
--w------- 1 root root 4096 Jul 4 13:50 new_id
--w------- 1 root root 4096 Jul 4 13:50 unbind
A simpler way to find the interface is with the following command:
[root@host]# ls -l /sys/bus/usb/drivers/reping/*/reping
-rw-r--r-- 1 root root 0 Jul 4 13:51 /sys/bus/usb/drivers/reping/1-2:1.0/reping
Now we can test the device.
[root@host]# echo "Countdown: 5 4 3 2 1" > /sys/bus/usb/drivers/reping/1-2:1.0/reping
[root@host]# cat /sys/bus/usb/drivers/reping/1-2:1.0/reping
1 2 3 4 5 :nwodtnuoC
|