Sei sulla pagina 1di 19

AVR309 USB to UART protocol converter

Features: a) Using microcontrollers with hardware-


• USB protocol implemented in firmware – low implemented USB interface. It is necessary
cost USB solution for small devices to know how USB works and write firmware
• Supports Low Speed USB (1.5Mbit/s) in into microcontroller accordingly. Additionally,
accordance with USB1.1 and USB2.0 it is necessary to create a driver on the
• Implementation runs on very small AVR devices, computer side (as long as the operating
from 2kBytes and up. system does not include standard USB
• Only one external component required for USB classes). The disadvantage (and this is the
connection (one resistor) main disadvantage for small vendors and
• Very small footprint, starting from the S0-8 amateurs) is the lack of availability of this
AT90S2323 kind of microcontrollers and their high price
• Implemented functions: Direct I/O pin control, compared to simple "RS232"
USB to RS232 converter, EEPROM scratch microcontrollers.
register b) Second option is to use some universal
• User can implement own functions (USB to TWI converter between USB and another
control, USB A/D and D/A converter, …)
interface. This other interface will usually be
• Vendor customizable device name (visible from
user side)
RS232, 8-bit data bus, or TWI bus. In this
• Full PC side support: full documentation how to case there is no need for special firmware, it
access device (DLL library functions) isn’t even necessary to know how USB
• Examples for developers on how to works, and no driver writing is necessary as
communicate with device (Delphi, C++, Visual the converter vendor will offer one driver for
Basic) the whole solution. The disadvantage is the
higher price of the complete system, and the
greater dimensions of the complete product.
The solution presented in this document is a
Introduction USB implementation into a low-cost
The USB interface has become extremely microcontroller through emulation of the USB
popular, especially for the end use due to its protocol in the microcontroller firmware. The
simplicity for end user applications (Plug and main challenge for this design was obtaining
Play without restart). For developers, however, sufficient speed. The USB bus is quite fast:
USB implementation into their devices has been LowSpeed - 1.5Mbit/s, FullSpeed - 12Mbit/s,
more complicated when compared to e.g. HighSpeed - 480Mbit/s. The maximum speed of
RS232. In addition there is need of software a normal microcontroller is limited: AT89C2051 -
support on PC side: device drivers. Because of 2MIPS = 24MHz/(12cycl/inst.), PIC16F84 -
this, RS232 based communication is still very 5MIPS = 20MHz/(4cycl/inst.), AT90S23x3 -
popular among device manufacturers. This 10MIPS = 10MHz/(1cycl/inst.). There are higher-
interface is well-established and has good perfomance microcontrolers around, but they
operating system support, but recently the tend to have poor availability and high cost, as
physcal RS232 port has been removed from the well as being larger in size. For the reasons
standard PC interface, giving ground to USB described, AT90S1200/AT90S23x3 represent
ports. the least expensive solution which is still able to
Implementation of USB into external devices meet the hard speed requirements of LowSpeed
is at present time solved in two ways: USB. The solution is not recommended for
higher USB speeds.
Theory of Operation
Last Bit Bus Driven
of Packet to Idle State
Bus
Floats
EOP
Bus Idle
Extensive details regarding physical USB VOH (min)
Strobe

communication can be found at the website


www.usb.org. This documentation is very VSE (max)

complex and difficult for beginners (ca. 650 VSE (min)


VOL (max)
pages). VSS
A very good and simple explanation for Figure 2. Packet Transaction Voltage Levels
beginners can be found in the document USB in
a Nutshell. Making Sense of the USB Standard
written by Craig Peacock USB device connection and disconnection is
(Craig.Peacock@beyondlogic.org). This detected based on the impedance sensed on the
document can be found at USB line. For LowSpeed USB devices (our
http://www.beyondlogic.org or here: usb-in-a- case) a 1.5kohm pull-up resistor between DATA-
nutshell.pdf This document is recommended signal and VCC is necessary (for FullSpeed
reading for understanding how USB works (only devices, this resistor is connected to DATA+).
30 pages).
In this document the explanation is limited to R2
L.S. USB
the scope of understanding the device firmware. F.S./L.S. USB
D+ D+
Transceiver
The USB physical interface consists of 4 wires: 2 Transceiver
D-
R1 Untwisted, Unshielded
D- Slow Slew Rate
3 Meters max.
for powering the external device (VCC and R1
Buffers
R1=15K
GND), and 2 signal wires (DATA+ and DATA-). Host or R2=1.5K

The power wires give approximately 5 volts and Hub Port Low Speed Function

max. 500mA. We can supply our device from Figure 3. Low Speed Device Cable and
Vcc and GND. The signal wires named DATA+ Resistor Connections
and DATA- handle the communication between
host (computer) and device. Signals on these Based on this pull-up, the host computer will
wires are bi-directional. Voltage levels are detect that some new device is connected to
differential: when DATA+ is at high level, DATA- USB line.
is at low level, but there are some cases when
DATA+ and DATA- are at the same level (EOP – After the host detects a new device it can
end of packet, idle state). start communicating with it in accordance with
One Bit
Time
the physical USB protocol. The USB protocol,
(1.5Mb/s)
unlike UART, is based on synchronous data
transfer. Synchronization of transmitter and
VSE (max)
receiver is necessary to carry out the
Signal pins
pass output
Driver spec levels
Signal Pins with minimal
reflections and
communication. Because of this, the transmitter
VSE (min)
ringing
will transmit a small header (sync pattern)
VSS
preceding the actual data. This header is a
square wave (101010), succeed by two zeros
Figure 1. Low Speed Driver Signal after which the actual data is transmitted.
Waveforms
SYNC PATTERN

Therefore, in our firmware driven USB NRZI Data


Encoding
Idle PID0 PID1

implementation we must be able to sense or


drive both those signals. Figure 4. Sync Pattern

In order to maintain synchronization, USB


VOH (min)
demands that this sync pattern is transmitted
VSE (max) every millisecond in the case of full speed
VSE (min) devices, or that both signal lines are pulled to
VOL (max)
VSS Bus Idle zero in the case of low speed devices. In
SOP First Bit hardware-implemented USB receivers, this
of Packet
synchronization is ensured by a digital PLL
(phase locked loop). In our implementation, we
must synchronize data sampling time with the
sync pattern, then wait for two zeros, and start Isochronous Transfer, and Bulk Transfer. Each
receiving data. of these transfers is dedicated for different
Data reception on USB must satisfy that device requirements, and their explanations can
receiver and transmitter are in sync at all times, be found in [0].
therefore it is not permitted to send a stream of Our device is using Control transfer. This
continuous zeros or ones on the data lines. The transfer mode is dedicated for device settings,
USB protocol ensures synchronization by bit but can also be used for general purposes.
stuffing. This means that, after 6 continuous Implementation of Control transfer must exist on
ones or zeros on the data lines, one single every USB device, as this mode is used for
change (one bit) is inserted. As signal on USB configuration when the device is connected
lines are NRZI coded, this means that one zero (obtaining information from device, setting
bit is inserted into the logical data stream after 6 device address, etc.). A description of the
contiguous logical ones. Control transfer and its contents can be found in
0 1 1 0 1 0 1 0 0 0 1 0 0 1 1 0
[0] and [0]. Each Control transfer consists of
Data Idle several stages: Setup stage, Data stage and
Status stage.
NRZI Idle Data is in USB transferred in packets, with
several bytes each. The packet size is
Figure 5. NRZI Data Encoding
determined by each device, but is limited by
specification. For LowSpeed devices, packet
Data Encoding Sequence: size is limited to 8 bytes. This 8 bytes long
Raw Data packed + beginning and ending field must be
Sync Pattern Packet Data

Stuffed Bit
received into the device buffer in one USB
Bit Stuffed Data
transfer. In hardware-based USB receivers, the
Sync Pattern Packet Data various parts of the transfer are automatically
Six Ones
decoded, and the device is notified only when
NRZI Idle
Encoded Data Sync Pattern Packet Data
the entire message has been assigned for the
particular device. In a firmware implementation,
Figure 6. Bit Stuffing the USB message must be decoded by firmware
after the entire message has been received into
Notification of end of data transfer is made the buffer. This gives us the requirements and
by and EOP (end-of-packet) part. EOP consists limitations: The device must have a buffer for
of 2 zeros on both data lines (both physical storing the whole USB message length, another
DATA+ and DATA- are at low voltage level). buffer for USB transmitting (prepared data to
EOP is succeeded by a short time of idle state transmit), and administration overhead with
(min 2 periods of data rate). After this, the next message decoding and checking. Additionally, of
transaction can be performed. course, the firmware is required to perform fast
TPERIOD and precise synchronous speed reception (from
Data physical pins to buffer) and transmission (from
Differential Crossover
Data Lines Level buffer to pins). All these capabilities are limited
by microcontroller resources (speed and
EOP
Width program/data memory capacity), so the firmware
must be carefully optimized. In some cases the
Figure 7. EOP Width Timing microcontroller computation power is very close
to the minimum requirements and therefore all
Data between sync pattern and EOP is NRZI firmware must be written in assembly.
coded communication between USB device and
host. The data stream is composed by packets
consisting of several fields: Sync field (sync
Connection
pattern), PacketID (PID), Address field (ADDR), A schematic diagram of microcontroller
Endpoint field (ENDP), Data, and Cyclic connection to USB bus is shown in Figure 8 and
redundancy check field (CRC). Usage of these Figure 9. These schematics were made for the
fields in different types of data transfer is specific purpose as USB to RS232 converter.
explained well in [0]. USB describes four types of The functions implemented by direct pin control
transfer: Control Transfer, Interrupt Transfer, and EEPROM read/write.
VCC VCC
IC1
AT90S2313-10 / ATtiny2313
XT1
12MHz R1 +
RS232 TTL 2k2
VCC
1 20 C2
RST VCC GND GND 10u
RxD 2 19 D7
PD0/RXD SCK/PB7
TxD 3 18 D6 D1 D2 GND
PD1/TXD MISO/PB6 C1 R2
4 17 D5 3V6 3V6
XTAL2 MOSI/PB5 100n 4k7
5 16 D4 XC1
XTAL1 PB4
6 15 D3 GND USB-A
PD2/INT0 OC1/PB3
D0 7 14 68R GND
PD3/INT1 PB2 GND 4
8 13 DATA+
PD4/T0 AN1/PB1 R2 3
D1 9 12 DATA-
PD5/T1 AN2/PB0 R3 2
10 11 D2 VCC
GND ICP/PD6 68R VCC 1
GND

Figure 8. USB interface with AT90S2313 (as USB to RS232 converter with 32 byte FIFO + 8-bit I/O
control + 128 bytes EEPROM)

IC1 VCC VCC


ATmega8
Dc6/RST 1 28 Dc5
PC6/RST PC5/ADC5/SCL R1
RxD 2 27 Dc4 +
RS232 TTL PD0/RXD PC4/ADC4/SDA C1 2k2
TxD 3 26 Dc3
PD1/TXD PC3/ADC3 C2 100n
4 25 Dc2 10u
PD2/INT0 PC2/ADC2
Dd3 5 24 Dc1
PD3/INT1 PC1/ADC1
Dd4 6 23 Dc0 GND GND
PD4/T0/XCK PC0/ADC0 R2
7 22
VCC VCC GND GND 4k7
8 21 GND GND
GND GND AREF VCC
9 20
XTAL1/TOSC1/PB6 AVCC D1 D2
10 19 Db5
XTAL2/TOSC2/PB7 PB5/SCK 3V6 3V6
XT1 Dd5 11 18 Db4
PD5/T1 PB4/MISO
12MHz Dd6 12 17 Db3 GND
PD6/AIN0 PB3/MOSI/OC2
Dd7 13 16 Db2
PD7/AIN1 PB2/SS/OCIB XC1
14 15
PB0/ICP PB1/OC1A R3 USB-A
68R GND
GND 4
DATA+
3
DATA-
R4 2
VCC
68R VCC 1

Figure 9. USB interface with ATmega8 (as USB to RS232 converter with 800 byte FIFO + EEPROM + I/O
control + EEPROM)
The USB data lines, DATA- and DATA+, are recognizes a valid USB packet with the given
connected to pins PB0 and PB1 on the AVR. USB address. Therefore this is a critical part of
This connection cannot be changed because the the USB answer.
firmware makes use of one AVR finesse for fast After the reception of this bitstream, we
signal reception: The bit signal captured from the obtain an NRZI coded array of bits with
data lines is right shifted from LSB (PB0) to carry bitstuffing in the input buffer. In the decoding
and then to the reception register, which collects process we first remove the bitstuffing and then
the bits from the data lines. PB1 is used as input the NRZI coding. All these changes are made in
signal because on 8-pin AT90S2323 this pin can a second buffer (copy of the reception buffer), so
be used as external interrupt INT0 (no additional a new packet can be received while the first one
connection to INT0 is necessary – the 8-pin is being decoded. At this point, decoding speed
version of the AVR is the smallest pin count is not so important, because the device can
available). On other AVRs, an external delay the answer, but when the hosts asks for an
connection from DATA+ to the INT0 pin is answer during decoding, the device must answer
necessary if we want to ensure no firmware immediately with NAK so that the host will
changes between different AVR microcontrollers. understand it is not ready yet. Because of this,
For proper USB device connection and the firmware must be able to receive packets
signaling, the AVR acting as low speed USB from the host during decoding, decode whether
device must have a 1.5kohm pull-up resistor on the transaction is intended for the device, and
DATA-. then send NAK packet if there is some decoding
The other components only provide in progress. The host will then ask again. The
functions for proper operation of the firmware also decodes the main USB transaction
microcontroller: Crystal as clock source, and and performs the requested action (for example,
capacitors for power supply filtering. send char to RS232 line and wait for
This small component count is sufficient to transmission complete), and prepares the
obtain a functional USB device, which can corresponding answer. During this process the
communicate with a computer through the USB device is interrupted by some packets from the
interface. This is a very simple and cheap host, usually IN packets to obtain answer from
solution. Some additional components can be the device. To these IN packets, the device must
added to extend the device functions. If we want answer with NAK handshake packets. When the
to receive an IR signal, we can add the answer is ready and the device has performed
TSOP1738 infrared sensor. If we want to use the the required action, the answer must go through
device as an USB to RS232 converter, we CRC field addition and then NRZI coding and
should add the MAX232 TTL to RS232 level bitstuffing before being transmitted as an array
converter. If we want to control LED diodes or of bits. Now, when the host requests an answer,
display, we connect them to I/O pins directly or we can transmit this bitstream to the data lines
through resistors. according to the USB specification (from sync
pattern to EOP).
Implementation
All USB protocol reception and decoding is Firmware description
performed at the firmware level. The firmware In the following we describe the main parts
first receives a stream of USB bits in one USB of the firmware. The firmware is divided into
packet into the internal buffer. Start of reception blocks: interrupt routines, decoding routines
is based on the external interrupt INT0, which (NRZI decoding, bitstuffing removal/addition, …),
takes care of the sync pattern. During reception, USB reception, USB transmission, requested
only the end of packet signal is checked (EOP action decoding, and performing requested
detection only). This is due to the extreme speed actions.
of the USB data transfer. After a successful User can add his own functions to the
reception, the firmware will decode the data firmware. Some examples on how to make
packets and analyze them. At first it checks if the customer-specific functions can be found in the
packet is intended for this device according to its firmware code, and user can write new device
address. The address is transferred in every extensions according to the existing built-in
USB transaction and therefore the device will functions. For example TWI support can be
know if the next transferred data are dedicated added according to the built-in function for direct
to it. USB address decoding must be done very pin control.
quickly, because the device must answer with an
ACK handshake packet to the USB host if it
INT0 raising edge 1

Packet type detection


Edge detection

USB address detection


Wait for end of SOP (if no Data packet)
(2 bits at same level)

Sampling time to middle of bit Is my USB 2


Init USB data bits receiving address?

Sample DATA+, Set state according


DATA- to PB0, PB1 received type of packet

Send answer (if answer


prepared in out buffer)
PB0=PB1=0 or NACK (answer in
? progress)

Shift PB0  carry


Shiftbuffer  carry Is Setup data 2
packed?

Shiftbuffer Send ACK packet (accepting setup data


full? packet).
Copy receiving buffer to input buffer.
Set flag for new request in input buffer.

Store Shiftbuffer to
input buffer Finish INT0 interrupt:
Clear pending INT0 2
Restore registers

End of INT0 interrupt

Received 2
bytes < 3 ?

“EXT_INT0” Service
Figure 10. Flowchart of receiving routine
Interrupt Routine
The external have only 8 cycles will be performed. check the action
interrupt 0 is active for data bit This is in order to flag: what to do
all the time while sampling, storing it free the reception when some
the firmware is into the buffer byte, buffer to receive a received data are
running. This shift the buffer byte, new packet. present. In addition
routine initiates the checking if the During it checks whether
reception of USB whole byte has reception the packet the USB interface is
serial data (an been received, type is decoded and reset (both data
alternative name storing this byte into the corresponding lines are at low level
would be “USB SRAM, and flag value is set. for a long time) and,
reception”). An checking for EOP. This flag is tested in if it is, reinitializes
external interrupt This is perhaps the the main program the device. When
occurs on a rising most crucial part of loop, and according there is something
edge on the INT0 the firmware; to its value the to do (action flag
pin (a rising edge everything must be appropriate action active), the
marks the beginning done synchronously will be taken and corresponding
of the sync pattern with exact timing. the corresponding action is called:
of a USB packet When a whole USB answer will be decoding NRZI in
see Figure 4). This packet has been prepared with no packet, bitstuffing
activates the USB received, packet regard to removal and
reception routine. decoding must be microcontroller preparation of the
First, data performed. First, we speed requested answer in
sampling must be must quickly requirements. the transmit buffer
synchronized to the determine the The INT0 must (with bitstuffing and
middle of the bit packet type be allowed to keep NRZI coding). Then
width. This is done (SETUP, IN, OUT, its very fast one flag is activated
according to the DATA) and received invocation time in all to signal that the
sync pattern (which USB address. This firmware routines, answer is prepared
is a square wave fast decoding must so no interrupt for sending.
signal). Because bit be performed inside disabling is allowed Physical output
duration is only 8 the interrupt service and during other buffer transmission
cycles of the XTAL routine because an interrupts’ execution to the USB lines is
clocks and interrupt answer is required (for example serial performed in the
occurrence can be very quickly after line receive reception routine as
delayed (+/- 4 receiving the USB interrupt) INT0 must answer to the IN
cycles), edge packet (the device be enabled. Fast packet.
synchronization in must answer with reception in the
sync pattern must an ACK handshake INT0 interrupt Short
be carefully packet when a routine is very
performed. End of packet with the important, and it is description
sync pattern and device address has necessary to of used
begin of data bits been received, and optimize the
are detected with NAK when the firmware for speed
firmware
according to the last packet is for the and exact timing. subroutines
dual low level bits in device, but when no One important issue In the following,
sync packet (see answer is currently is register backup the firmware
Figure 4). ready). optimization in subroutines and
After this, data At the end of interrupt routines. their purposes are
sampling is started. the reception described briefly.
Sampling is routine (after Main Reset:
performed in the ACK/NAK Initialization of
middle of the bit. handshake packet program the AVR
Because data rate has been sent) the loop microcontroller
is 1.5Mbit/s sampled data buffer The main resources: stack,
(1.5MHz) and the must be copied into program loop is serial lines, USB
microcontroller another buffer on very simple. It is buffers, interrupts...
speed is 12MHz, we which the decoding only required to Main:
Main program USB reset: handshake packet). ShiftDeleteBuf
loop. Checks the Initializes USB This buffer is fer:
action flag value interface to default frequently sent as Auxiliary routine
and, if flag is set, values (as the state answer so it is for use when
performs the after power on). always kept ready performing
required action. SendPrepared in memory. bitstuffing removal.
Additionally, this USBAnswer: SendNAK: Removes one bit to
routine checks for Sends prepared Transmits NAK output data buffer
USB reset on data output buffer packet to USB lines. and thus decreases
lines and contents to USB ComposeSTA the buffer length.
reinitializes the USB lines. NRZI coding LL: The remainder of
microcontroller and bitstuffing is Initializes buffer the buffer is shifted
interface if this is performed during in RAM with STALL in.
the case. transmission. data (STALL MirrorInBuffer
Int0Handler: Packet is ended handshake packet). Bytes:
The interrupt with EOP. This buffer is Exchanges but
service routine for ToggleDATAPI frequently sent as order in byte
the INT0 external D: answer so it is because data is
interrupt. Main Toggles always kept ready received from USB
reception/transmissi DATAPID packet in memory. lines to buffer in
on engine; identifier (PID) DecodeNRZI: reverse order
emulation from USB between DATA0 Performs NRZI (LSB/MSB).
data lines. Storing and DATA1 PID. decoding. Data from CheckCRCIn:
data to buffer, This toggling is USB lines in buffer Performs CRC
decision of USB necessary during is NRZI coded. This (cyclic redundancy
packet owners transmission as per routine removes the check) on received
(USB address), the USB NRZI coding from data packet. CRC is
packet recognition, specification. the data. added to USB
sending answer to ComposeZero BitStuff: packet to detect
USB host. Basically DATA1PIDAnswer: Removes/adds data corruption.
the heart of the Composes zero bitstuffing in AddCRCOut:
USB engine. answer for received USB data. Adds CRC field
MyNewUSBAd transmission. Zero Bitstuffing is added into output data
dress: answer contains no by host hardware packet. CRC is
Called from data and is used in according to the calculated
INT0 reception some cases as USB specification to according to the
routine if there is a answer when no ensure USB specification
request present to additional data is synchronization in from given USB
change the USB available on device. data sampling. This fields.
address. The InitACKBufffer routine produces CheckCRC:
address is changed : received data Auxiliary routine
and its coded NRZI Initializes buffer without bitstuffing or used in CRC
equivalent for in RAM with ACK data to transmit with checking and
fastest address data (ACK bitstuffing. addition.
decoding during handshake packet). ShiftInsertBuff LoadDescripto
USB packet This buffer is er: rFromROM:
reception is frequently sent as Auxiliary routine Loads data from
prepared. answer so it is for use when ROM to USB output
FinishReceivin always kept ready in performing buffer (as USB
g: memory. bitstuffing addition. answer).
Copies coded SendACK: Adds one bit to LoadDescripto
raw data from USB Transmits ACK output data buffer rFromROMZeroIns
reception packet to packet to USB lines. and thus increases ert:
decoding packet InitNAKBufffer: the buffer length. Loads data from
(for NRZI and Initializes buffer The remainder of ROM to USB output
bitstuffing in RAM with NAK the buffer is shifted buffer (as USB
decoding). data (NAK out. answer) but every
even byte is added Routine is ComposeGET Data structures
as zero. This is divided into two big _CONFIGURATIO (USB descriptors
used when a string parts: N: and strings):
descriptor in - standard ComposeSET_ DeviceDescrip
UNICODE format is requests CONFIGURATION; tor:
requested (ROM - vendor ComposeGET ConfigDescrip
saving). specific _INTERFACE; tor:
LoadDescripto requests ComposeSET_ LangIDStringD
rFromSRAM: Standard INTERFACE: escriptor:
Loads data from requests are ComposeSYN VendorStringD
RAM to USB output necessary and are CH_FRAME; escriptor:
buffer (as USB described in USB DevNameStrin
answer). specification Vendor USB gDescriptor:
LoadDescripto (SET_ADDRESS, functions (Vendor
rFromEEPROM: GET_DESCRIPTO requests): Format of
Loads data from R, …). DoSetInfraBuff
data EEPROM to Vendor specific erEmpty: input
USB output buffer requests are DoGetInfraCod message
(as USB answer). requests that can e:
LoadXXXDesc obtain vendor DoSetDataPort
from USB
riptor: specific data (in Direction: host
Performs Control USB DoGetDataPor As stated
selection for answer transfer). Control IN tDirection: above, our USB
source location: USB transfer is DoSetOutData device uses USB
ROM, RAM or used for this AVR Port: Control Transfer.
EEPROM. device to DoGetOutData This type of transfer
PrepareUSBO communicate with Port: uses a data format
utAnswer: host. Developers DoGetInDataP defined in the USB
Prepares USB can add into this ort: specification
answer to output part their own DoEEPROMRe described in usb-in-
buffer according to functions and in this ad: a-nutshell.pdf [0] on
request by USB manner extend DoEEPROMWr page 13 (Control
host, and performs device versatility. ite: Transfers). In this
the requested The various DoRS232Send document the
action. Adds documented built-in : details and
bitstuffing to functions in the DoRS232Read explanations on
answer. source code can be : how control transfer
PrepareUSBA used as templates DoSetRS232B works, and
nswer: on how to add aud: therefore how our
Main routine for custom functions. DoGetRS232B device
performing the aud: communicates with
required action and Standard USB DoGetRS232B the USB host, can
preparing the functions (Standard uffer: be found. The AVR
corresponding Requests): DoSetRS232D device is using
answer. The routine ComposeGET ataBits: control IN endpoint.
will first determine _STATUS: DoGetRS232D A nice example of
which action to ComposeCLE ataBits: data communication
perform – discover AR_FEATURE: DoSetRS232P can be found on
function number ComposeSET_ arity: page 15 of [0].
from received input FEATURE: DoGetRS232P Communication
data packet – and ComposeSET_ arity: between host and
then perform the ADDRESS: DoSetRS232St AVR device is done
requested function. ComposeGET opBits: according to this
Function _DESCRIPTOR: DoGetRS232St example.
parameters are ComposeSET_ opBits: In addition to
located in input data DESCRIPTOR: the actual control
packet. transfer, the format
of the DATA0/1 field device after power
in the transfer on. This packet
should be uses the Standard wValue wIndex wLength Data
discussed. Control Type request in the Feature Zero Zero None
transfer defines in bmRequestType Selector Interface
its setup stage a field (bits D6-D5 = Endpoint
standard request, 0). All next fields’
which is 8 bytes (bRequest, wValue, Zero Zero One Configuration
long. Its format is wIndex, wLength) Value
described on page meanings can be
26 of [0] (The Setup found in the USB Descriptor Zero or Descriptor Descriptor
Packet). There is specification. Their Type and Language Length
table with a explanation can be Descriptor ID
description of the found on pages 27- Index
meaning of every 30 in [0] (Standard
byte. The following Requests). Zero Interface One Alternate
is important for our Every setup Interface
purpose: packet has eight
Standard setup bytes, used as Zero Zero Two Device,
packet used for described in the Interface Interface, or
Endpoint Endpoint
detection and following table.
Status
configuration of
Field Size Value Device
Description Zero Zero None
Address
bmRequestType 1 Bit-map Characteristics of request
Configuration Zero Zero None
Value
D7 Data xfer direction
0 = Host to device
1 = Descriptor
Device to host Zero or Descriptor Descriptor
Type and Language Length
D6..5 TypeDescriptor ID
Index
0 = Standard
1 = Class
Feature
2 = Vendor Zero Zero None
Selector
3 = Reserved Interface
Endpoint
D4..0 Recipient
Alternate
0 = Device Interface Zero None
Setting
1 = Interface
2 = Endpoint
3 = Other
Zero Endpoint Two Frame Number
4..31 = Reserved
Table 2: Standard device requests
bRequest 1 Value Specific request (refer to
source not found)

wValue 2 Value Word-sized field that varies according


wValue to wIndex wLength Data
request
(param1) (param2)
wIndex 2 IndexFNCNumberDoSetInfraBufferEmpty
or Word sized field that varies according
Noneto None 1 Status
Offset request - typically used to pass an index or
offset
FNCNumberDoGetInfraCode None None 1 Status

wLength 2 Count Number of bytes to transfer if there is a


FNCNumberDoSetDataPortDirection DDRB DDRD 1 Status
data phase

Table 1 : Standard setup packet fields (control DDRC usedports


transfer)
etDataPortDirection None None FNCNumberDoGetRS232StopBits
3 DDRB None None 1 Stopbits
value
DDRC
Table 3: Vendor device requests used in
DDRD firmware as functions calls
Note: FNCNumberXXX values are defined in
oSetOutDataPort PORTB PORTD 1 Status
DLL.
PORTC usedports

oGetOutDataPort None None 3 PORTB

PORTC

PORTD

oGetInDataPort None None 3 PINB

PINC

PIND

oEEPROMRead Address None Length EEPROM


bytes

oEEPROMWrite Address EEPROM 1 Status


value

DoRS232Send RS232 None 1 Status


byte value

DoRS232Read None None 2 Status

oSetRS232Baud Baudrate Baudrate 1 Status


Lo Hi

oGetRS232Baud None None 2 Baudrate

oGetRS232Buffer None None Length RS232


bytes
from FIFO

SetRS232DataBits Databits None 1 Status


value

GetRS232DataBits None None 1 Databits


value

oSetRS232Parity Parity None 1 Status


value

oGetRS232Parity None None 1 Parity


value

SetRS232StopBits Stopbits None 1 Status


value
from vendor of USB device and must be
Control Transfer is used for user assigned from USB organization (see more
communication, implemented as custom information on [1]). Every vendor has its own ID
functions in the firmware, as well. The Vendor and therefore this value can not be changed to
Type request in the bmRequestType field (bits any unassigned value. But product ID depends
D6-D5 = 2) is used. In this case all succeeding only from vendor choice and purpose of PID is to
fields (bRequest, wValue, wIndex) can be recognize different devices from the same
modified according to the programmer’s vendor.
purposes. In our implementation, bRequest field
is used for function number and the next fields Computer side software
are used for function parameters. The first
parameter is in the wValue slot, the second at
the wIndex location. In order to communicate with the device we
An example from the implementation is need some software support on the PC side.
EEPROM writing. bRequest = 9 is chosen as This software is divided into 3 levels:
function number. The wValue field is used for 1) Device driver: Used for low-level
EEPROM address, and the value to write communication with the device and for
(EEPROM data) is in the wIndex field. According installation into operating system
to this, we obtain the following function: (Windows98/ME/NT/XP).
EEPROMWrite(Address, Value). 2) DLL library: Used for encapsulation of
If more user functions are required, it is device functions and communication with
enough to add function numbers and the body of device driver. DLL simplifies the device
the required function into the firmware. The function access from user applications., It
technique can be extracted from the built-in includes some device and operating
function in the firmware (see source code). system related functions (threads, buffers,
USB host also communicates with device etc.).
with IN control transfers. Host sends an 8-byte 3) User application: Makes user
IN data packet to the device in the format interface for friendly communication
defined above (function number and between user and device. Uses function
parameters), and the device then answers with calls from DLL library only.
requested data. The length of the answered data
is firmware limited in some cases up to 255 Device driver and installation
bytes, but the main limitation is on the device files
driver side on the host computer. Now this driver The first time we connect the USB device to
supports 8-byte length answers (in Vendor Type the computer USB port, the operating system will
requests. detect the device and request driver files. This is
called device installation. For the installation
Firmware customization process it is necessary not only to make the
Users (developers of device) can add into device driver, but also an installation script in
firmware new functions and extend device which the installation steps are described.
properties.
In firmware are prepared 3 examples how to The device driver for the device described in
add user functions: DoUserFunctionX (X=0,1,2). this document is made with Windows2000 DDK
According these examples can be added similar (Driver Development Kit). The development of
extended functions. Functions content depends the USB driver is based on one of the included
only on device requirements. examples in the DDK – IsoUsb. This driver was
In firmware can be customized also all modified for our purpose – AVR USB device
device names – as device appears in computer communication. In the original source code,
side. This names is located in firmware as parts have been extended/added about the
strings and can be changed to any string. But IOCTL communications, because our device
these names are recommended to change communicates with the computer through these
together with USB PID (product ID) and VID IOCTL calls. To reduce the driver code size,
(vendor ID) for correct recognition in system. unused parts have been removed (read and
VID together with PID must be unique for write routines). The name of the driver is
given device type. Therefore is recommended “AVR309.sys” and it works as sender of
that if device functionality is changed then is commands to the USB device (Control IN
modified PID and/or VID. Vendor ID depends
transfers). The driver will work on all 32-bit rapidly write application using only the DLL
Windows versions except Win95. interface. There is no need to study the low-level
An installation script written in an INF file is device functions, as the DLL library separates
used during device installation. In this INF file the application programmer level from the
the various installation steps are described. The hardware level.
file “AVR309.inf” was created in the notepad text All functions exported from DLL are
editor. This file is requested by the operating described bellow. The declaration is written for
system during installation. During the installation the 3 mostly used programming languages:
process, the driver file is copied into the system Borland Delphi, C++ (Borland or Microsoft) and
and the required system changes are made. The Visual Basic. A more detailed description of
INF file ensures installation of the DLL library to these functions can be found in the included help
the system search path for easy reach from file AVR309_DLL_help.htm.
various applications.
Three files are necessary for device UART speed error discussion
installation: INF file “AVR309.inf”, driver Microcontroller uses 12MHz clock because
“AVR309.sys”, and DLL library “AVR309.dll”. the USB sampling. But using this clock value has
disadvantage that baudrate speed generating
DLL library contains small error for the standard baudrates.
The DLL library communicates with the But high value of clock minimizes this error.
device driver and all device functions are Maximum error that can be accepted in baudrate
implemented in this library. This way, generation is cca 4%: because maximum error is
programming of end-user applications is half bit duration (0.5) and the maximum packet
simplified. The DLL library ensures exclusive time is 12bits = 1start bit + 8data bits + 1parity
access to the device (serializes device access), bit + 2stop bits. Then the error is: 0.5/12*100% =
contains system buffer for RS232 data reception, 4.1%.
and creates a single system thread for device Function in DLL automatically checks this
RS232 data buffer reading. error and set baudrate to microcontroller only if
Serialization in DLL ensures that only one the error is bellow 4% (and returns error in case
application/thread will communicate with the of unsupported baudrate).
device at any given time. This is necessary In the next table is summarized the error of
because of the possibility of mixing question and standard baudrates in case of use 12MHz clock.
answer from various applications at the same
time. Standard Baudrate in Error [%]
System buffer for RS232 data reception baudrates AVR
ensures that the data received from the device’s 600 602 +0.33
RS232 line is stored into one buffer that is 1200 1204 +0.33
common to all applications. This way, data 2400 2408 +0.33
received by the device will be sent to all
4800 4808 +0.17
applications. There is no danger that an
9600 9616 +0.17
application will receive incomplete data because
some other application has read some of the 19200 19230 +0.16
data before. 28800 28846 +0.16
Only one system thread exists for all 38400 38462 +0.16
applications, and will periodically request device 57600 57692 +0.16
for RS232 data. The thread will then store 115200 115384 +0.16
received data into the system buffer. Only one Table 4: AVR UART baudrate errors (12MHz
system buffer solution ensures small CPU usage clock)
(in comparison to every application having their
own thread) and simplifies storing data into the
system buffer.
All device functions are defined in the DLL
library, and they are exported in a user-friendly
form: not as function number and parameters,
but as tidy function names with parameters.
Some functions are more complex internally, as
the function for RS232 buffer data read. This
way, developers of end-user applications can
Function prototype in "AVR309.dll" library:

Delphi:
const
AVR309DLL= 'AVR309.dll';
//return values from AVR309DLL functions:
NO_ERROR = 0;
DEVICE_NOT_PRESENT = 1;
NO_DATA_AVAILABLE = 2;
INVALID_BAUDRATE = 3;
OVERRUN_ERROR = 4;
INVALID_DATABITS = 5;
INVALID_PARITY = 6;
INVALID_STOPBITS = 7;

function DoGetInfraCode(var TimeCodeDiagram:array of byte; var DiagramLength:integer):integer; stdcall external AVR309DLL name 'DoGetInfraCode';
function DoSetDataPortDirection(DirectionByte:byte):integer; stdcall external AVR309DLL name 'DoSetDataPortDirection';
function DoGetDataPortDirection(var DataDirectionByte:byte):integer; stdcall external AVR309DLL name 'DoGetDataPortDirection';
function DoSetOutDataPort(DataOutByte:byte):integer; stdcall external AVR309DLL name 'DoSetOutDataPort';
function DoGetOutDataPort(var DataOutByte:byte):integer; stdcall external AVR309DLL name 'DoGetOutDataPort';
function DoGetInDataPort(var DataInByte:byte):integer; stdcall external AVR309DLL name 'DoGetInDataPort';
function DoSetDataPortDirections(DirectionByteB, DirectionByteC, DirectionByteD, UsedPorts:byte):integer; stdcall external AVR309DLL name
'DoSetDataPortDirections';
function DoGetDataPortDirections(var DataDirectionByteB, DirectionByteC, DirectionByteD, UsedPorts:byte):integer; stdcall external AVR309DLL name
'DoGetDataPortDirections';
function DoSetOutDataPorts(DataOutByteB, DataOutByteC, DataOutByteD, UsedPorts:byte):integer; stdcall external AVR309DLL name 'DoSetOutDataPorts';
function DoGetOutDataPorts(var DataOutByteB, DataOutByteC, DataOutByteD, UsedPorts:byte):integer; stdcall external AVR309DLL name
'DoGetOutDataPorts';
function DoGetInDataPorts(var DataInByteB, DataInByteC, DataInByteD, UsedPorts:byte):integer; stdcall external AVR309DLL name 'DoGetInDataPorts';

function DoEEPROMRead(Address:word; var DataInByte:byte):integer; stdcall external AVR309DLL name 'DoEEPROMRead';


function DoEEPROMWrite(Address:word; DataOutByte:byte):integer; stdcall external AVR309DLL name 'DoEEPROMWrite';
function DoRS232Send(DataOutByte:byte):integer; stdcall external AVR309DLL name 'DoRS232Send';
function DoRS232Read(var DataInByte:byte):integer; stdcall external AVR309DLL name 'DoRS232Read';
function DoSetRS232Baud(BaudRate:integer):integer; stdcall external AVR309DLL name 'DoSetRS232Baud';
function DoGetRS232Baud(var BaudRate:integer):integer; stdcall external AVR309DLL name 'DoGetRS232Baud';
function DoGetRS232Buffer(var RS232Buffer:array of byte; var RS232BufferLength:integer):integer; stdcall external AVR309DLL name 'DoGetRS232Buffer';
function DoRS232BufferSend(var RS232Buffer:array of byte; var RS232BufferLength:integer):integer; stdcall external AVR309DLL name 'DoRS232BufferSend';
function DoSetRS232DataBits(DataBits:byte):integer; stdcall external AVR309DLL name 'DoSetRS232DataBits';
function DoGetRS232DataBits(var DataBits:byte):integer; stdcall external AVR309DLL name 'DoGetRS232DataBits';
function DoSetRS232Parity(Parity:byte):integer; stdcall external AVR309DLL name 'DoSetRS232Parity';
function DoGetRS232Parity(var Parity:byte):integer; stdcall external AVR309DLL name 'DoGetRS232Parity';
function DoSetRS232StopBits(StopBits:byte):integer; stdcall external AVR309DLL name 'DoSetRS232StopBits';
function DoGetRS232StopBits(var StopBits:byte):integer; stdcall external AVR309DLL name 'DoGetRS232StopBits';

C++ Builder / Microsoft Visual C++:


#ifdef __cplusplus
extern "C" {
#endif

#define AVR309DLL "AVR309.dll";


//return values from AVR309DLL functions:
#define NO_ERROR 0;
#define DEVICE_NOT_PRESENT 1;
#define NO_DATA_AVAILABLE 2;
#define INVALID_BAUDRATE 3;
#define OVERRUN_ERROR 4;
#define INVALID_DATABITS 5;
#define INVALID_PARITY 6;
#define INVALID_STOPBITS 7;

int __stdcall DoGetInfraCode(uchar * TimeCodeDiagram, int DummyInt, int * DiagramLength);


int __stdcall DoSetDataPortDirection(uchar DirectionByte);
int __stdcall DoGetDataPortDirection(uchar * DataDirectionByte);
int __stdcall DoSetOutDataPort(uchar DataOutByte);
int __stdcall DoGetOutDataPort(uchar * DataOutByte);
int __stdcall DoGetInDataPort(uchar * DataInByte);
int __stdcall DoSetDataPortDirections(uchar DirectionByteB, uchar DirectionByte, uchar DirectionByte, uchar UsedPorts);
int __stdcall DoGetDataPortDirections(uchar * DataDirectionByteB, uchar * DataDirectionByteC, uchar * DataDirectionByteD, uchar * UsedPorts);
int __stdcall DoSetOutDataPorts(uchar DataOutByteB, uchar DataOutByteC, uchar DataOutByteD, uchar UsedPorts);
int __stdcall DoGetOutDataPorts(uchar * DataOutByteB, uchar * DataOutByteC, uchar * DataOutByteD, uchar * UsedPorts);
int __stdcall DoGetInDataPorts(uchar * DataInByteB, uchar * DataInByteC, uchar * DataInByteD, uchar * UsedPorts);
int __stdcall DoEEPROMRead(ushort Address, uchar * DataInByte);
int __stdcall DoEEPROMWrite(ushort Address, uchar DataOutByte);
int __stdcall DoRS232Send(uchar DataOutByte);
int __stdcall DoRS232Read(uchar * DataInByte);
int __stdcall DoSetRS232Baud(int BaudRate);
int __stdcall DoGetRS232Baud(int * BaudRate);
int __stdcall DoGetRS232Buffer(uchar * RS232Buffer, int DummyInt, int * RS232BufferLength);
int __stdcall DoRS232BufferSend(uchar * RS232Buffer, int DummyInt, int * RS232BufferLength);
int __stdcall DoSetRS232DataBits(uchar DataBits);
int __stdcall DoGetRS232DataBits(uchar * DataBits);
int __stdcall DoSetRS232Parity(uchar Parity);
int __stdcall DoGetRS232Parity(uchar * Parity);
int __stdcall DoSetRS232StopBits(uchar StopBits);
int __stdcall DoGetRS232StopBits(uchar * StopBits);

#ifdef __cplusplus
}
#endif

Visual Basic:
Public Const AVR309DLL="AVR309.dll";
'return values from AVR309DLL functions:
Public Const NO_ERROR = 0;
Public Const DEVICE_NOT_PRESENT = 1;
Public Const NO_DATA_AVAILABLE = 2;
Public Const INVALID_BAUDRATE = 3;
Public Const OVERRUN_ERROR = 4;
Public Const INVALID_DATABITS = 5;
Public Const INVALID_PARITY = 6;
Public Const INVALID_STOPBITS = 7;
Public Declare Function DoGetInfraCode Lib "AVR309.dll" (ByRef TimeCodeDiagram As Any, ByVal DummyInt As Long, ByRef DiagramLength As Long) As
Long
Public Declare Function DoSetDataPortDirection Lib "AVR309.dll" (ByVal DirectionByte As Byte) As Long
Public Declare Function DoGetDataPortDirection Lib "AVR309.dll" (ByRef DataDirectionByte As Byte) As Long
Public Declare Function DoSetOutDataPort Lib "AVR309.dll" (ByVal DataOutByte As Byte) As Long
Public Declare Function DoGetOutDataPort Lib "AVR309.dll" (ByRef DataOutByte As Byte) As Long
Public Declare Function DoGetInDataPort Lib "AVR309.dll" (ByRef DataInByte As Byte) As Long
Public Declare Function DoSetDataPortDirections Lib "AVR309.dll" (ByVal DirectionByteB As Byte, ByVal DirectionByteC As Byte, ByVal DirectionByteD As
Byte, ByVal UsedPorts As Byte) As Long
Public Declare Function DoGetDataPortDirections Lib "AVR309.dll" (ByRef DataDirectionByteB As Byte, ByRef DataDirectionByteC As Byte, ByRef
DataDirectionByteD As Byte, ByRef UsedPorts As Byte) As Long
Public Declare Function DoSetOutDataPorts Lib "AVR309.dll" (ByVal DataOutByteB As Byte, ByVal DataOutByteC As Byte, ByVal DataOutByteD As Byte,
ByVal UsedPorts As Byte) As Long
Public Declare Function DoGetOutDataPorts Lib "AVR309.dll" (ByRef DataOutByteB As Byte, ByRef DataOutByteC As Byte, ByRef DataOutByteD As Byte,
ByRef UsedPorts As Byte) As Long
Public Declare Function DoGetInDataPorts Lib "AVR309.dll" (ByRef DataInByteB As Byte, ByRef DataInByteC As Byte, ByRef DataInByteD As Byte, ByRef
UsedPorts As Byte) As Long
Public Declare Function DoEEPROMRead Lib "AVR309.dll" (ByVal Address As Word, ByRef DataInByte As Byte) As Long
Public Declare Function DoEEPROMWrite Lib "AVR309.dll" (ByVal Address As Word, ByVal DataOutByte As Byte) As Long
Public Declare Function DoRS232Send Lib "AVR309.dll" (ByVal DataOutByte As Byte) As Long
Public Declare Function DoRS232Read Lib "AVR309.dll" (ByRef DataInByte As Byte) As Long
Public Declare Function DoSetRS232Baud Lib "AVR309.dll" (ByVal BaudRate As Long) As Long
Public Declare Function DoGetRS232Baud Lib "AVR309.dll" (ByRef BaudRate As Long) As Long
Public Declare Function DoGetRS232Buffer Lib "AVR309.dll" (ByRef RS232Buffer As Any, ByVal DummyInt As Long, ByRef RS232BufferLength As Long)
As Long
Public Declare Function DoRS232BufferSend Lib "AVR309.dll" (ByRef RS232Buffer As Any, ByVal DummyInt As Long, ByRef RS232BufferLength As Long)
As Long
Public Declare Function DoSetRS232DataBits Lib "AVR309.dll" (DataBits As Byte) As Long
Public Declare Function DoGetRS232DataBits Lib "AVR309.dll" (ByRef DataBits As Byte) As Long
Public Declare Function DoSetRS232Parity Lib "AVR309.dll" (Parity As Byte) As Long
Public Declare Function DoGetRS232Parity Lib "AVR309.dll" (ByRef Parity As Byte) As Long
Public Declare Function DoSetRS232StopBits Lib "AVR309.dll" (StopBits As Byte) As Long
Public Declare Function DoGetRS232StopBits Lib "AVR309.dll" (ByRef StopBits As Byte) As Long
End user application be written using this example as starting point,
The end-user application will only use and in several programming languages (Delphi,
functions from the DLL library to communicate C++, Visual Basic).
with the device. Its main purpose is to make a There is included an example of an end user
user-friendly GUI (graphical user interface). application called “AVR309demo.exe”. This
Application programmers use the DLL library software is only meant as an example on how to
to write their own applications. An example can use the functions from the DLL library. The
be found in the published project where all the source code can be used as a template for other
source code is available. Many applications can applications.
Appendix A: Source code of firmware for ATmega8 AVR
Source code of firmware for ATmega8 AVR microcontroller was written in AVR Studio 4. Source code is in text file
USBtoRS232.asm or in syntax highlighted form file USBtoRS232asm.pdf.

Appendix B: AVR309.dll interface


Library AVR309.dll was written in Delphi3 therefore its source code is based on Object Pascal language. But in the next
is described interface also for other programming languages: Delphi, C/C++ and Visual Basic.
Interface to DLL library (exported functions) “AVR309.dll” are described in file AVR309_DLL_help.htm.

Appendix C: DLL library AVR309.dll source code


Whole source code of AVR309.dll library written in Delphi3 is in file AVR309.dpr (Delphi3 project).

Appendix D: End user application example - AVR309USBdemo.exe (with source


code)
Example of using DLL library from end user application is software AVR309USBdemo.exe. Whole source codes as
Delphi3 project of this example application: AVR309USBdemo.dpr.
Used documentation and resources

http://www.cesko.host.sk - authors web pages and various projects

USB related resources:


[0] http://www.usb.org - USB specification and another USB related resources
[0] usb-in-a-nutshell.pdf from http://www.beyondlogic.org/usbnutshell/usb-in-a-nutshell.pdf - very
good and simple document how USB works
[0] http://www.beyondlogic.org - USB related resources
[0] enumeration.pdf - exact pictures how USB enumeration works
[0] http://mes.loyola.edu/faculty/phs/usb1.html
[0] http://www.mcu.cz - USB section (in Czech/Slovak language)
[0] crcdes.pdf – implementation CRC in USB
[0] USBspec1-1.pdf – USB 1.1 specification
[0] usb_20.pdf – USB 2.0 specification

AVR related resources:

[0] http://www.atmel.com - AVR 8-bit microcontrollers family


[0] doc0839.pdf – AT90S2313 datasheet (URL http://www.atmel.com/atmel/acrobat/doc0839.pdf )
[0] doc2486.pdf – ATmega8 datasheet
[0] avr910.pdf – AVR ISP programming
[0] http://www.avrfreaks.com - a lot of AVR resources and information
[0] AVR Studio 4 – debugging tool for the AVR family (from http://www.atmel.com)
[0] Simple LPT ISP programmer (http://www.hw.cz/products/lpt_isp_prog/index.html)

Driver related resources:

[0] http://www.beyondlogic.org - USB related resources about USB drivers


[0] http://www.cypress.com - fully documented USB driver (for USB thermometer)
[0] http://www.jungo.com - WinDriver and KernetDriver – easy to use USB drivers
[0] http://microsoft.com Microsoft Windows DDK – Driver Development Kit – tools for drivers writing

Author:
Ing. Igor Cesko
Slovakia
www.cesko.host.sk
cesko@internet.sk

Potrebbero piacerti anche