No changes between revisions
/Designs/Tools/i2c_AVR_USB/SW/firmware/COPYING |
---|
0,0 → 1,341 |
GNU GENERAL PUBLIC LICENSE |
Version 2, June 1991 |
Copyright (C) 1989, 1991 Free Software Foundation, Inc. |
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
Preamble |
The licenses for most software are designed to take away your |
freedom to share and change it. By contrast, the GNU General Public |
License is intended to guarantee your freedom to share and change free |
software--to make sure the software is free for all its users. This |
General Public License applies to most of the Free Software |
Foundation's software and to any other program whose authors commit to |
using it. (Some other Free Software Foundation software is covered by |
the GNU Library General Public License instead.) You can apply it to |
your programs, too. |
When we speak of free software, we are referring to freedom, not |
price. Our General Public Licenses are designed to make sure that you |
have the freedom to distribute copies of free software (and charge for |
this service if you wish), that you receive source code or can get it |
if you want it, that you can change the software or use pieces of it |
in new free programs; and that you know you can do these things. |
To protect your rights, we need to make restrictions that forbid |
anyone to deny you these rights or to ask you to surrender the rights. |
These restrictions translate to certain responsibilities for you if you |
distribute copies of the software, or if you modify it. |
For example, if you distribute copies of such a program, whether |
gratis or for a fee, you must give the recipients all the rights that |
you have. You must make sure that they, too, receive or can get the |
source code. And you must show them these terms so they know their |
rights. |
We protect your rights with two steps: (1) copyright the software, and |
(2) offer you this license which gives you legal permission to copy, |
distribute and/or modify the software. |
Also, for each author's protection and ours, we want to make certain |
that everyone understands that there is no warranty for this free |
software. If the software is modified by someone else and passed on, we |
want its recipients to know that what they have is not the original, so |
that any problems introduced by others will not reflect on the original |
authors' reputations. |
Finally, any free program is threatened constantly by software |
patents. We wish to avoid the danger that redistributors of a free |
program will individually obtain patent licenses, in effect making the |
program proprietary. To prevent this, we have made it clear that any |
patent must be licensed for everyone's free use or not licensed at all. |
The precise terms and conditions for copying, distribution and |
modification follow. |
GNU GENERAL PUBLIC LICENSE |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
0. This License applies to any program or other work which contains |
a notice placed by the copyright holder saying it may be distributed |
under the terms of this General Public License. The "Program", below, |
refers to any such program or work, and a "work based on the Program" |
means either the Program or any derivative work under copyright law: |
that is to say, a work containing the Program or a portion of it, |
either verbatim or with modifications and/or translated into another |
language. (Hereinafter, translation is included without limitation in |
the term "modification".) Each licensee is addressed as "you". |
Activities other than copying, distribution and modification are not |
covered by this License; they are outside its scope. The act of |
running the Program is not restricted, and the output from the Program |
is covered only if its contents constitute a work based on the |
Program (independent of having been made by running the Program). |
Whether that is true depends on what the Program does. |
1. You may copy and distribute verbatim copies of the Program's |
source code as you receive it, in any medium, provided that you |
conspicuously and appropriately publish on each copy an appropriate |
copyright notice and disclaimer of warranty; keep intact all the |
notices that refer to this License and to the absence of any warranty; |
and give any other recipients of the Program a copy of this License |
along with the Program. |
You may charge a fee for the physical act of transferring a copy, and |
you may at your option offer warranty protection in exchange for a fee. |
2. You may modify your copy or copies of the Program or any portion |
of it, thus forming a work based on the Program, and copy and |
distribute such modifications or work under the terms of Section 1 |
above, provided that you also meet all of these conditions: |
a) You must cause the modified files to carry prominent notices |
stating that you changed the files and the date of any change. |
b) You must cause any work that you distribute or publish, that in |
whole or in part contains or is derived from the Program or any |
part thereof, to be licensed as a whole at no charge to all third |
parties under the terms of this License. |
c) If the modified program normally reads commands interactively |
when run, you must cause it, when started running for such |
interactive use in the most ordinary way, to print or display an |
announcement including an appropriate copyright notice and a |
notice that there is no warranty (or else, saying that you provide |
a warranty) and that users may redistribute the program under |
these conditions, and telling the user how to view a copy of this |
License. (Exception: if the Program itself is interactive but |
does not normally print such an announcement, your work based on |
the Program is not required to print an announcement.) |
These requirements apply to the modified work as a whole. If |
identifiable sections of that work are not derived from the Program, |
and can be reasonably considered independent and separate works in |
themselves, then this License, and its terms, do not apply to those |
sections when you distribute them as separate works. But when you |
distribute the same sections as part of a whole which is a work based |
on the Program, the distribution of the whole must be on the terms of |
this License, whose permissions for other licensees extend to the |
entire whole, and thus to each and every part regardless of who wrote it. |
Thus, it is not the intent of this section to claim rights or contest |
your rights to work written entirely by you; rather, the intent is to |
exercise the right to control the distribution of derivative or |
collective works based on the Program. |
In addition, mere aggregation of another work not based on the Program |
with the Program (or with a work based on the Program) on a volume of |
a storage or distribution medium does not bring the other work under |
the scope of this License. |
3. You may copy and distribute the Program (or a work based on it, |
under Section 2) in object code or executable form under the terms of |
Sections 1 and 2 above provided that you also do one of the following: |
a) Accompany it with the complete corresponding machine-readable |
source code, which must be distributed under the terms of Sections |
1 and 2 above on a medium customarily used for software interchange; or, |
b) Accompany it with a written offer, valid for at least three |
years, to give any third party, for a charge no more than your |
cost of physically performing source distribution, a complete |
machine-readable copy of the corresponding source code, to be |
distributed under the terms of Sections 1 and 2 above on a medium |
customarily used for software interchange; or, |
c) Accompany it with the information you received as to the offer |
to distribute corresponding source code. (This alternative is |
allowed only for noncommercial distribution and only if you |
received the program in object code or executable form with such |
an offer, in accord with Subsection b above.) |
The source code for a work means the preferred form of the work for |
making modifications to it. For an executable work, complete source |
code means all the source code for all modules it contains, plus any |
associated interface definition files, plus the scripts used to |
control compilation and installation of the executable. However, as a |
special exception, the source code distributed need not include |
anything that is normally distributed (in either source or binary |
form) with the major components (compiler, kernel, and so on) of the |
operating system on which the executable runs, unless that component |
itself accompanies the executable. |
If distribution of executable or object code is made by offering |
access to copy from a designated place, then offering equivalent |
access to copy the source code from the same place counts as |
distribution of the source code, even though third parties are not |
compelled to copy the source along with the object code. |
4. You may not copy, modify, sublicense, or distribute the Program |
except as expressly provided under this License. Any attempt |
otherwise to copy, modify, sublicense or distribute the Program is |
void, and will automatically terminate your rights under this License. |
However, parties who have received copies, or rights, from you under |
this License will not have their licenses terminated so long as such |
parties remain in full compliance. |
5. You are not required to accept this License, since you have not |
signed it. However, nothing else grants you permission to modify or |
distribute the Program or its derivative works. These actions are |
prohibited by law if you do not accept this License. Therefore, by |
modifying or distributing the Program (or any work based on the |
Program), you indicate your acceptance of this License to do so, and |
all its terms and conditions for copying, distributing or modifying |
the Program or works based on it. |
6. Each time you redistribute the Program (or any work based on the |
Program), the recipient automatically receives a license from the |
original licensor to copy, distribute or modify the Program subject to |
these terms and conditions. You may not impose any further |
restrictions on the recipients' exercise of the rights granted herein. |
You are not responsible for enforcing compliance by third parties to |
this License. |
7. If, as a consequence of a court judgment or allegation of patent |
infringement or for any other reason (not limited to patent issues), |
conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot |
distribute so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you |
may not distribute the Program at all. For example, if a patent |
license would not permit royalty-free redistribution of the Program by |
all those who receive copies directly or indirectly through you, then |
the only way you could satisfy both it and this License would be to |
refrain entirely from distribution of the Program. |
If any portion of this section is held invalid or unenforceable under |
any particular circumstance, the balance of the section is intended to |
apply and the section as a whole is intended to apply in other |
circumstances. |
It is not the purpose of this section to induce you to infringe any |
patents or other property right claims or to contest validity of any |
such claims; this section has the sole purpose of protecting the |
integrity of the free software distribution system, which is |
implemented by public license practices. Many people have made |
generous contributions to the wide range of software distributed |
through that system in reliance on consistent application of that |
system; it is up to the author/donor to decide if he or she is willing |
to distribute software through any other system and a licensee cannot |
impose that choice. |
This section is intended to make thoroughly clear what is believed to |
be a consequence of the rest of this License. |
8. If the distribution and/or use of the Program is restricted in |
certain countries either by patents or by copyrighted interfaces, the |
original copyright holder who places the Program under this License |
may add an explicit geographical distribution limitation excluding |
those countries, so that distribution is permitted only in or among |
countries not thus excluded. In such case, this License incorporates |
the limitation as if written in the body of this License. |
9. The Free Software Foundation may publish revised and/or new versions |
of the General Public License from time to time. Such new versions will |
be similar in spirit to the present version, but may differ in detail to |
address new problems or concerns. |
Each version is given a distinguishing version number. If the Program |
specifies a version number of this License which applies to it and "any |
later version", you have the option of following the terms and conditions |
either of that version or of any later version published by the Free |
Software Foundation. If the Program does not specify a version number of |
this License, you may choose any version ever published by the Free Software |
Foundation. |
10. If you wish to incorporate parts of the Program into other free |
programs whose distribution conditions are different, write to the author |
to ask for permission. For software which is copyrighted by the Free |
Software Foundation, write to the Free Software Foundation; we sometimes |
make exceptions for this. Our decision will be guided by the two goals |
of preserving the free status of all derivatives of our free software and |
of promoting the sharing and reuse of software generally. |
NO WARRANTY |
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
REPAIR OR CORRECTION. |
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGES. |
END OF TERMS AND CONDITIONS |
How to Apply These Terms to Your New Programs |
If you develop a new program, and you want it to be of the greatest |
possible use to the public, the best way to achieve this is to make it |
free software which everyone can redistribute and change under these terms. |
To do so, attach the following notices to the program. It is safest |
to attach them to the start of each source file to most effectively |
convey the exclusion of warranty; and each file should have at least |
the "copyright" line and a pointer to where the full notice is found. |
<one line to give the program's name and a brief idea of what it does.> |
Copyright (C) 19yy <name of author> |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Also add information on how to contact you by electronic and paper mail. |
If the program is interactive, make it output a short notice like this |
when it starts in an interactive mode: |
Gnomovision version 69, Copyright (C) 19yy name of author |
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
This is free software, and you are welcome to redistribute it |
under certain conditions; type `show c' for details. |
The hypothetical commands `show w' and `show c' should show the appropriate |
parts of the General Public License. Of course, the commands you use may |
be called something other than `show w' and `show c'; they could even be |
mouse-clicks or menu items--whatever suits your program. |
You should also get your employer (if you work as a programmer) or your |
school, if any, to sign a "copyright disclaimer" for the program, if |
necessary. Here is a sample; alter the names: |
Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
`Gnomovision' (which makes passes at compilers) written by James Hacker. |
<signature of Ty Coon>, 1 April 1989 |
Ty Coon, President of Vice |
This General Public License does not permit incorporating your program into |
proprietary programs. If your program is a subroutine library, you may |
consider it more useful to permit linking proprietary applications with the |
library. If this is what you want to do, use the GNU Library General |
Public License instead of this License. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/Makefile-avrusb.mega8 |
---|
0,0 → 1,84 |
# Name: Makefile |
# Project: USB I2C |
# Author: Christian Starkjohann, modified for I2C USB by Till Harbaum |
# Creation Date: 2005-03-20 |
# Tabsize: 4 |
# Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
# License: Proprietary, free under certain conditions. See Documentation. |
# This Revision: $Id: Makefile-avrusb.mega8,v 1.1 2006/12/03 21:28:59 harbaum Exp $ |
SERIAL = `echo /dev/tty.[Uu][Ss]*` |
UISP = uisp -dprog=stk200 |
# UISP = uisp -dprog=avr910 -dserial=$(SERIAL) -dpart=auto |
# The two lines above are for "uisp" and the AVR910 serial programmer connected |
# to a Keyspan USB to serial converter to a Mac running Mac OS X. |
# Choose your favorite programmer and interface. |
DEFINES += -DDEBUG |
DEFINES += -DDEBUG_LEVEL=1 |
COMPILE = avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 $(DEFINES) |
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o |
# symbolic targets: |
all: firmware.hex |
.c.o: |
$(COMPILE) -c $< -o $@ |
.S.o: |
$(COMPILE) -x assembler-with-cpp -c $< -o $@ |
# "-x assembler-with-cpp" should not be necessary since this is the default |
# file type for the .S (with capital S) extension. However, upper case |
# characters are not always preserved on Windows. To ensure WinAVR |
# compatibility define the file type manually. |
.c.s: |
$(COMPILE) -S $< -o $@ |
# Fuse high byte: |
# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000) |
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0 |
# | | | | | +-------- BOOTSZ1 |
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) |
# | | | +-------------- CKOPT (full output swing) |
# | | +---------------- SPIEN (allow serial programming) |
# | +------------------ WDTON (WDT not always on) |
# +-------------------- RSTDISBL (reset pin is enabled) |
# Fuse low byte: |
# 0x9f = 1 0 0 1 1 1 1 1 |
# ^ ^ \ / \--+--/ |
# | | | +------- CKSEL 3..0 (external >8M crystal) |
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) |
# | +------------------ BODEN (BrownOut Detector enabled) |
# +-------------------- BODLEVEL (2.7V) |
fuse: |
$(UISP) --wr_fuse_h=0xc9 --wr_fuse_l=0x9f |
clean: |
rm -f firmware.hex firmware.lst firmware.obj firmware.cof firmware.list firmware.map firmware.eep.hex firmware.bin *.o usbdrv/*.o firmware.s usbdrv/oddebug.s usbdrv/usbdrv.s |
# file targets: |
firmware.bin: $(OBJECTS) |
$(COMPILE) -o firmware.bin $(OBJECTS) |
firmware.hex: firmware.bin |
rm -f firmware.hex firmware.eep.hex |
avr-objcopy -j .text -j .data -O ihex firmware.bin firmware.hex |
./checksize firmware.bin 8192 960 |
# do the checksize script as our last action to allow successful compilation |
# on Windows with WinAVR where the Unix commands will fail. |
program: firmware.hex |
avrdude -c usbasp -p atmega8 -U lfuse:w:0x9f:m -U hfuse:w:0xc9:m -U flash:w:firmware.hex |
program-nodep: |
avrdude -c usbasp -p atmega8 -U lfuse:w:0x9f:m -U hfuse:w:0xc9:m -U flash:w:firmware.hex |
disasm: firmware.bin |
avr-objdump -d firmware.bin |
cpp: |
$(COMPILE) -E main.c |
/Designs/Tools/i2c_AVR_USB/SW/firmware/Makefile-avrusb.tiny45 |
---|
0,0 → 1,74 |
# Name: Makefile |
# Project: USB I2C |
# Author: Christian Starkjohann, modified for I2C USB by Till Harbaum |
# Creation Date: 2005-03-20 |
# Tabsize: 4 |
# Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
# License: Proprietary, free under certain conditions. See Documentation. |
# This Revision: $Id: Makefile-avrusb.tiny45,v 1.3 2007/06/07 13:53:47 harbaum Exp $ |
# DEFINES += -DDEBUG |
# DEFINES += -DDEBUG_LEVEL=1 |
DEFINES += -DF_CPU=12000000 |
COMPILE = avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=attiny45 $(DEFINES) |
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o |
# symbolic targets: |
all: firmware.hex |
.c.o: |
$(COMPILE) -c $< -o $@ |
.S.o: |
$(COMPILE) -x assembler-with-cpp -c $< -o $@ |
# "-x assembler-with-cpp" should not be necessary since this is the default |
# file type for the .S (with capital S) extension. However, upper case |
# characters are not always preserved on Windows. To ensure WinAVR |
# compatibility define the file type manually. |
.c.s: |
$(COMPILE) -S $< -o $@ |
# Fuse high byte: |
# 0x5f = 0 1 0 1 1 1 1 1 <-- BODLEVEL0 (Brown out trigger level bit 0) |
# ^ ^ ^ ^ ^ ^ ^------ BODLEVEL1 (Brown out trigger level bit 1) |
# | | | | | +-------- BODLEVEL2 (Brown out trigger level bit 2) |
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) |
# | | | +-------------- WDTON (WDT not always on) |
# | | +---------------- SPIEN (allow serial programming) |
# | +------------------ DWEN (ebug wire is enabled) |
# +-------------------- RSTDISBL (reset pin is disabled) |
# Fuse low byte: |
# 0xdf = 1 1 0 1 1 1 1 1 |
# ^ ^ \ / \--+--/ |
# | | | +------- CKSEL 3..0 (external >8M crystal) |
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) |
# | +------------------ CKOUT (clock output enable) |
# +-------------------- CKDIV8 (divide clock by eight disabled) |
clean: |
rm -f firmware.lst firmware.obj firmware.cof firmware.list firmware.map *.bin *.o */*.o *~ */*~ firmware.s usbdrv/oddebug.s usbdrv/usbdrv.s |
# file targets: |
firmware.bin: $(OBJECTS) |
$(COMPILE) -o firmware.bin $(OBJECTS) |
firmware.hex: firmware.bin |
rm -f firmware.hex firmware.eep.hex |
avr-objcopy -j .text -j .data -O ihex firmware.bin firmware.hex |
./checksize firmware.bin 4096 196 |
# do the checksize script as our last action to allow successful compilation |
# on Windows with WinAVR where the Unix commands will fail. |
program: firmware.hex |
avrdude -P/dev/ttyS0 -c stk500hvsp -p attiny45 -U lfuse:w:0xdf:m -U flash:w:firmware.hex -U hfuse:w:0x5f:m |
program-usb: firmware.hex |
avrdude -P/dev/ttyUSB0 -c stk500hvsp -p attiny45 -U lfuse:w:0xdf:m -U flash:w:firmware.hex -U hfuse:w:0x5f:m |
disasm: firmware.bin |
avr-objdump -d firmware.bin |
cpp: |
$(COMPILE) -E main.c |
/Designs/Tools/i2c_AVR_USB/SW/firmware/Makefile-usbtiny.mega8 |
---|
0,0 → 1,17 |
# ====================================================================== |
# Makefile for i2c-tiny-usb |
# |
# Copyright (C) 2006 Till Harbaum |
# |
# This is free software, licensed under the terms of the GNU General |
# Public License as published by the Free Software Foundation. |
# ====================================================================== |
USBTINY = ./usbtiny |
TARGET_ARCH = -DF_CPU=12000000 -DUSBTINY -mmcu=atmega8 |
OBJECTS = main.o |
FLASH_CMD = avrdude -c usbasp -p atmega8 -U lfuse:w:0x9f:m -U hfuse:w:0xc9:m -U flash:w:main.hex |
STACK = 32 |
FLASH = 8192 |
SRAM = 1024 |
include $(USBTINY)/common.mk |
/Designs/Tools/i2c_AVR_USB/SW/firmware/Makefile-usbtiny.tiny45 |
---|
0,0 → 1,19 |
# ====================================================================== |
# Makefile for i2c-tiny-usb |
# |
# Copyright (C) 2006 Till Harbaum |
# |
# This is free software, licensed under the terms of the GNU General |
# Public License as published by the Free Software Foundation. |
# ====================================================================== |
USBTINY = ./usbtiny |
TARGET_ARCH = -DF_CPU=12000000 -DUSBTINY -mmcu=attiny45 |
OBJECTS = main.o |
TTY = /dev/ttyUSB0 |
# TTY = /dev/ttyS0 |
FLASH_CMD = avrdude -P$(TTY) -c stk500hvsp -p attiny45 -U lfuse:w:0xdf:m -U hfuse:w:0x5f:m -U flash:w:main.hex |
STACK = 32 |
FLASH = 4096 |
SRAM = 256 |
include $(USBTINY)/common.mk |
/Designs/Tools/i2c_AVR_USB/SW/firmware/checksize |
---|
0,0 → 1,35 |
#!/bin/sh |
# Name: checksize |
# Project: AVR Make system |
# Author: Christian Starkjohann |
# Creation Date: 2004-12-29 |
# Tabsize: 4 |
# Copyright: (c) 2005 OBJECTIVE DEVELOPMENT Software GmbH. |
# Revision: $Id: checksize,v 1.1.1.1 2006/11/09 18:27:00 harbaum Exp $ |
error=0 |
codelimit=2048 # default value |
datalimit=96 # default value; leave 32 bytes for stack |
if [ $# -gt 1 ]; then |
codelimit="$2" |
fi |
if [ $# -gt 2 ]; then |
datalimit="$3" |
fi |
set -- `avr-size -d "$1" | awk '/[0-9]/ {print $1 + $2, $2 + $3, $2}'` |
if [ $1 -gt $codelimit ]; then |
echo "*** code size $1 exceeds limit of $codelimit" |
error=1 |
else |
echo "ROM: $1 bytes (data=$3)" |
fi |
if [ $2 -gt $datalimit ]; then |
echo "*** data size $2 exceeds limit of $datalimit" |
error=1 |
else |
echo "RAM: $2 bytes" |
fi |
exit $error |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/Designs/Tools/i2c_AVR_USB/SW/firmware/main.c |
---|
0,0 → 1,578 |
/* Name: main.c |
* Project: i2c-tiny-usb |
* Author: Till Harbaum |
* Tabsize: 4 |
* Copyright: (c) 2005 by Till Harbaum <till@harbaum.org> |
* License: GPL |
* This Revision: $Id: main.c,v 1.9 2007/06/07 13:53:47 harbaum Exp $ |
* |
* $Log: main.c,v $ |
* Revision 1.9 2007/06/07 13:53:47 harbaum |
* Version number fixes |
* |
* Revision 1.8 2007/05/19 12:30:11 harbaum |
* Updated USB stacks |
* |
* Revision 1.7 2007/04/22 10:34:05 harbaum |
* *** empty log message *** |
* |
* Revision 1.6 2007/01/05 19:30:58 harbaum |
* i2c clock bug fix |
* |
* Revision 1.5 2007/01/03 18:35:07 harbaum |
* usbtiny fixes and pcb layouts |
* |
* Revision 1.4 2006/12/03 21:28:59 harbaum |
* *** empty log message *** |
* |
* Revision 1.3 2006/11/22 19:12:45 harbaum |
* Added usbtiny support |
* |
* Revision 1.2 2006/11/14 19:15:13 harbaum |
* *** empty log message *** |
* |
*/ |
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include <avr/pgmspace.h> |
#include <avr/wdt.h> |
#include <util/delay.h> |
#ifndef USBTINY |
// use avrusb library |
#include "usbdrv.h" |
#include "oddebug.h" |
#else |
// use usbtiny library |
#include "usb.h" |
#include "usbtiny.h" |
typedef byte_t uchar; |
#if! defined (__AVR_ATtiny45__) |
#define USBDDR DDRC |
#define USB_CFG_IOPORT PORTC |
#else |
#define USBDDR DDRB |
#define USB_CFG_IOPORT PORTB |
#endif |
#define USB_CFG_DMINUS_BIT USBTINY_DMINUS |
#define USB_CFG_DPLUS_BIT USBTINY_DPLUS |
#define usbInit() usb_init() |
#define usbPoll() usb_poll() |
#endif |
#define ENABLE_SCL_EXPAND |
/* commands from USB, must e.g. match command ids in kernel driver */ |
#define CMD_ECHO 0 |
#define CMD_GET_FUNC 1 |
#define CMD_SET_DELAY 2 |
#define CMD_GET_STATUS 3 |
#define CMD_I2C_IO 4 |
#define CMD_I2C_BEGIN 1 // flag fo I2C_IO |
#define CMD_I2C_END 2 // flag fo I2C_IO |
/* linux kernel flags */ |
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */ |
#define I2C_M_RD 0x01 |
#define I2C_M_NOSTART 0x4000 |
#define I2C_M_REV_DIR_ADDR 0x2000 |
#define I2C_M_IGNORE_NAK 0x1000 |
#define I2C_M_NO_RD_ACK 0x0800 |
/* To determine what functionality is present */ |
#define I2C_FUNC_I2C 0x00000001 |
#define I2C_FUNC_10BIT_ADDR 0x00000002 |
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ |
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_QUICK 0x00010000 |
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 |
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 |
#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 |
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 |
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 |
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 |
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 |
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 |
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 |
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ |
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ |
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ |
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ |
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ |
#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ |
I2C_FUNC_SMBUS_WRITE_BYTE |
#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ |
I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ |
I2C_FUNC_SMBUS_WRITE_WORD_DATA |
#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA |
#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ |
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ |
I2C_FUNC_SMBUS_BYTE | \ |
I2C_FUNC_SMBUS_BYTE_DATA | \ |
I2C_FUNC_SMBUS_WORD_DATA | \ |
I2C_FUNC_SMBUS_PROC_CALL | \ |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ |
I2C_FUNC_SMBUS_I2C_BLOCK |
/* the currently support capability is quite limited */ |
const unsigned long func PROGMEM = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
#ifdef DEBUG |
#define DEBUGF(format, args...) printf_P(PSTR(format), ##args) |
/* ------------------------------------------------------------------------- */ |
static int uart_putchar(char c, FILE *stream) { |
if (c == '\n') |
uart_putchar('\r', stream); |
loop_until_bit_is_set(UCSRA, UDRE); |
UDR = c; |
return 0; |
} |
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, |
_FDEV_SETUP_WRITE); |
#else |
#define DEBUGF(format, args...) |
#endif |
/* ------------------------------------------------------------------------- */ |
#define DEFAULT_DELAY 10 // default 10us (100khz) |
static unsigned short clock_delay = DEFAULT_DELAY; |
static unsigned short clock_delay2 = DEFAULT_DELAY/2; |
static unsigned short expected; |
static unsigned char saved_cmd; |
#if! defined (__AVR_ATtiny45__) |
#define I2C_PORT PORTC |
#define I2C_PIN PINC |
#define I2C_DDR DDRC |
#define I2C_SDA _BV(4) |
#define I2C_SCL _BV(5) |
#else |
#define I2C_PORT PORTB |
#define I2C_PIN PINB |
#define I2C_DDR DDRB |
#define I2C_SDA _BV(1) |
#define I2C_SCL _BV(5) |
#endif |
static void i2c_io_set_sda(uchar hi) { |
if(hi) { |
I2C_DDR &= ~I2C_SDA; // high -> input |
I2C_PORT |= I2C_SDA; // with pullup |
} else { |
I2C_DDR |= I2C_SDA; // low -> output |
I2C_PORT &= ~I2C_SDA; // drive low |
} |
} |
static uchar i2c_io_get_sda(void) { |
return(I2C_PIN & I2C_SDA); |
} |
static void i2c_io_set_scl(uchar hi) { |
#ifdef ENABLE_SCL_EXPAND |
_delay_loop_2(clock_delay2); |
if(hi) { |
I2C_DDR &= ~I2C_SCL; // port is input |
I2C_PORT |= I2C_SCL; // enable pullup |
// wait while pin is pulled low by client |
while(!(I2C_PIN & I2C_SCL)); |
} else { |
I2C_DDR |= I2C_SCL; // port is output |
I2C_PORT &= ~I2C_SCL; // drive it low |
} |
_delay_loop_2(clock_delay); |
#else |
_delay_loop_2(clock_delay2); |
if(hi) I2C_PORT |= I2C_SCL; // port is high |
else I2C_PORT &= ~I2C_SCL; // port is low |
_delay_loop_2(clock_delay); |
#endif |
} |
static void i2c_init(void) { |
/* init the sda/scl pins */ |
I2C_DDR &= ~I2C_SDA; // port is input |
I2C_PORT |= I2C_SDA; // enable pullup |
#ifdef ENABLE_SCL_EXPAND |
I2C_DDR &= ~I2C_SCL; // port is input |
I2C_PORT |= I2C_SCL; // enable pullup |
#else |
I2C_DDR |= I2C_SCL; // port is output |
#endif |
/* no bytes to be expected */ |
expected = 0; |
} |
/* clock HI, delay, then LO */ |
static void i2c_scl_toggle(void) { |
i2c_io_set_scl(1); |
i2c_io_set_scl(0); |
} |
/* i2c start condition */ |
static void i2c_start(void) { |
i2c_io_set_sda(0); |
i2c_io_set_scl(0); |
} |
/* i2c repeated start condition */ |
static void i2c_repstart(void) |
{ |
/* scl, sda may not be high */ |
i2c_io_set_sda(1); |
i2c_io_set_scl(1); |
i2c_io_set_sda(0); |
i2c_io_set_scl(0); |
} |
/* i2c stop condition */ |
void i2c_stop(void) { |
i2c_io_set_sda(0); |
i2c_io_set_scl(1); |
i2c_io_set_sda(1); |
} |
uchar i2c_put_u08(uchar b) { |
char i; |
for (i=7;i>=0;i--) { |
if ( b & (1<<i) ) i2c_io_set_sda(1); |
else i2c_io_set_sda(0); |
i2c_scl_toggle(); // clock HI, delay, then LO |
} |
i2c_io_set_sda(1); // leave SDL HI |
i2c_io_set_scl(1); // clock back up |
b = i2c_io_get_sda(); // get the ACK bit |
i2c_io_set_scl(0); // not really ?? |
return(b == 0); // return ACK value |
} |
uchar i2c_get_u08(uchar last) { |
char i; |
uchar c,b = 0; |
i2c_io_set_sda(1); // make sure pullups are activated |
i2c_io_set_scl(0); // clock LOW |
for(i=7;i>=0;i--) { |
i2c_io_set_scl(1); // clock HI |
c = i2c_io_get_sda(); |
b <<= 1; |
if(c) b |= 1; |
i2c_io_set_scl(0); // clock LO |
} |
if(last) i2c_io_set_sda(1); // set NAK |
else i2c_io_set_sda(0); // set ACK |
i2c_scl_toggle(); // clock pulse |
i2c_io_set_sda(1); // leave with SDL HI |
return b; // return received byte |
} |
#ifdef DEBUG |
void i2c_scan(void) { |
uchar i = 0; |
for(i=0;i<127;i++) { |
i2c_start(); // do start transition |
if(i2c_put_u08(i << 1)) // send DEVICE address |
DEBUGF("I2C device at address 0x%x\n", i); |
i2c_stop(); |
} |
} |
#endif |
/* ------------------------------------------------------------------------- */ |
struct i2c_cmd { |
unsigned char type; |
unsigned char cmd; |
unsigned short flags; |
unsigned short addr; |
unsigned short len; |
}; |
#define STATUS_IDLE 0 |
#define STATUS_ADDRESS_ACK 1 |
#define STATUS_ADDRESS_NAK 2 |
static uchar status = STATUS_IDLE; |
static uchar i2c_do(struct i2c_cmd *cmd) { |
uchar addr; |
DEBUGF("i2c %s at 0x%02x, len = %d\n", |
(cmd->flags&I2C_M_RD)?"rd":"wr", cmd->addr, cmd->len); |
/* normal 7bit address */ |
addr = ( cmd->addr << 1 ); |
if (cmd->flags & I2C_M_RD ) |
addr |= 1; |
if(cmd->cmd & CMD_I2C_BEGIN) |
i2c_start(); |
else |
i2c_repstart(); |
// send DEVICE address |
if(!i2c_put_u08(addr)) { |
DEBUGF("I2C read: address error @ %x\n", addr); |
status = STATUS_ADDRESS_NAK; |
expected = 0; |
i2c_stop(); |
} else { |
status = STATUS_ADDRESS_ACK; |
expected = cmd->len; |
saved_cmd = cmd->cmd; |
/* check if transfer is already done (or failed) */ |
if((cmd->cmd & CMD_I2C_END) && !expected) |
i2c_stop(); |
} |
/* more data to be expected? */ |
#ifndef USBTINY |
return(cmd->len?0xff:0x00); |
#else |
return(((cmd->flags & I2C_M_RD) && cmd->len)?0xff:0x00); |
#endif |
} |
#ifndef USBTINY |
uchar usbFunctionSetup(uchar data[8]) { |
static uchar replyBuf[4]; |
usbMsgPtr = replyBuf; |
#else |
extern byte_t usb_setup ( byte_t data[8] ) |
{ |
byte_t *replyBuf = data; |
#endif |
DEBUGF("Setup %x %x %x %x\n", data[0], data[1], data[2], data[3]); |
switch(data[1]) { |
case CMD_ECHO: // echo (for transfer reliability testing) |
replyBuf[0] = data[2]; |
replyBuf[1] = data[3]; |
return 2; |
break; |
case CMD_GET_FUNC: |
memcpy_P(replyBuf, &func, sizeof(func)); |
return sizeof(func); |
break; |
case CMD_SET_DELAY: |
/* The delay function used delays 4 system ticks per cycle. */ |
/* This gives 1/3us at 12Mhz per cycle. The delay function is */ |
/* called twice per clock edge and thus four times per full cycle. */ |
/* Thus it is called one time per edge with the full delay */ |
/* value and one time with the half one. Resulting in */ |
/* 2 * n * 1/3 + 2 * 1/2 n * 1/3 = n us. */ |
clock_delay = *(unsigned short*)(data+2); |
if(!clock_delay) clock_delay = 1; |
clock_delay2 = clock_delay/2; |
if(!clock_delay2) clock_delay2 = 1; |
DEBUGF("request for delay %dus\n", clock_delay); |
break; |
case CMD_I2C_IO: |
case CMD_I2C_IO + CMD_I2C_BEGIN: |
case CMD_I2C_IO + CMD_I2C_END: |
case CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END: |
// these are only allowed as class transfers |
return i2c_do((struct i2c_cmd*)data); |
break; |
case CMD_GET_STATUS: |
replyBuf[0] = status; |
return 1; |
break; |
default: |
// must not happen ... |
break; |
} |
return 0; // reply len |
} |
/*---------------------------------------------------------------------------*/ |
/* usbFunctionRead */ |
/*---------------------------------------------------------------------------*/ |
#ifndef USBTINY |
uchar usbFunctionRead( uchar *data, uchar len ) |
#else |
extern byte_t usb_in ( byte_t* data, byte_t len ) |
#endif |
{ |
uchar i; |
DEBUGF("read %d bytes, %d exp\n", len, expected); |
if(status == STATUS_ADDRESS_ACK) { |
if(len > expected) { |
DEBUGF("exceeds!\n"); |
len = expected; |
} |
// consume bytes |
for(i=0;i<len;i++) { |
expected--; |
*data = i2c_get_u08(expected == 0); |
DEBUGF("data = %x\n", *data); |
data++; |
} |
// end transfer on last byte |
if((saved_cmd & CMD_I2C_END) && !expected) |
i2c_stop(); |
} else { |
DEBUGF("not in ack state\n"); |
memset(data, 0, len); |
} |
return len; |
} |
/*---------------------------------------------------------------------------*/ |
/* usbFunctionWrite */ |
/*---------------------------------------------------------------------------*/ |
#ifndef USBTINY |
uchar usbFunctionWrite( uchar *data, uchar len ) |
#else |
extern void usb_out ( byte_t* data, byte_t len ) |
#endif |
{ |
uchar i, err=0; |
DEBUGF("write %d bytes, %d exp\n", len, expected); |
if(status == STATUS_ADDRESS_ACK) { |
if(len > expected) { |
DEBUGF("exceeds!\n"); |
len = expected; |
} |
// consume bytes |
for(i=0;i<len;i++) { |
expected--; |
DEBUGF("data = %x\n", *data); |
if(!i2c_put_u08(*data++)) |
err = 1; |
} |
// end transfer on last byte |
if((saved_cmd & CMD_I2C_END) && !expected) |
i2c_stop(); |
if(err) { |
DEBUGF("write failed\n"); |
//TODO: set status |
} |
} else { |
DEBUGF("not in ack state\n"); |
memset(data, 0, len); |
} |
#ifndef USBTINY |
return len; |
#endif |
} |
/* ------------------------------------------------------------------------- */ |
int main(void) { |
wdt_enable(WDTO_1S); |
#if DEBUG_LEVEL > 0 |
/* let debug routines init the uart if they want to */ |
odDebugInit(); |
#else |
#ifdef DEBUG |
/* quick'n dirty uart init */ |
UCSRB |= _BV(TXEN); |
UBRRL = F_CPU / (19200 * 16L) - 1; |
#endif |
#endif |
#ifdef DEBUG |
stdout = &mystdout; |
#endif |
DEBUGF("i2c-tiny-usb - (c) 2006 by Till Harbaum\n"); |
i2c_init(); |
#ifdef DEBUG |
i2c_scan(); |
#endif |
/* clear usb ports */ |
USB_CFG_IOPORT &= (uchar)~((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT)); |
/* make usb data lines outputs */ |
USBDDR |= ((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT)); |
/* USB Reset by device only required on Watchdog Reset */ |
_delay_loop_2(40000); // 10ms |
/* make usb data lines inputs */ |
USBDDR &= ~((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT)); |
usbInit(); |
sei(); |
for(;;) { /* main event loop */ |
wdt_reset(); |
usbPoll(); |
} |
return 0; |
} |
/* ------------------------------------------------------------------------- */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/readme.txt |
---|
0,0 → 1,38 |
i2c-tiny-usb - (c) 2006 by Till Harbaum |
--------------------------------------- |
http://www.harbaum.org/till/i2c_tiny_usb |
The firmware code itself is distributed under the GPL, but |
one of the usb codes comes under a separate license. Plase see |
the .txt files in usbdrv for details. |
The default configuration is for a attiny45. The Makefile.mega8 |
allows to compile the device for the Atmega8 cpu. This includes |
the possibility to use the atmega8 rs232 for debugging. |
The attiny45 has to be programmed in high voltage serial |
programming (hsvp) mode since this application needs the |
reset pin to be reconfigured for other use. |
This project supports two usb implementations: the avrusb and |
usbtiny. Due to this four Makefiles exist: |
Makefile-avrusb.tiny45 - build with avrusb for Attiny45 |
Makefile-avrusb.mega8 - build with avrusb for Atmega8 |
Makefile-usbtiny.tiny45 - build with usbtiny for Attiny45 |
Makefile-usbtiny.mega8 - build with usbtiny for Atmega8 |
Just type |
make -f Makefile-avrusb.xxx program |
or |
make -f Makefile-usbtiny.xxx flash |
to compile and upload the file. Please adjust e.g. programmer |
settings in the Makefile. |
If you don't want to recompile the firmware yourself you might |
use the included firmware.hex which is a prebuilt binary for the |
attiny45. Plase make sure you adjust the fuses accordingly. |
They need to be set to "external crystal > 8Mhz" and the RESET |
pin has to be disabled in order to be re-used for application |
specific purposes. See Makefile-avrusb.tiny45 for more details. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbconfig.h |
---|
0,0 → 1,121 |
/* Name: usbconfig.h |
* Project: AVR USB driver |
* Author: Christian Starkjohann, modified by Till Harbaum |
* Creation Date: 2005-04-01 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: Proprietary, free under certain conditions. See Documentation. |
* This Revision: $Id: usbconfig.h,v 1.4 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
#ifndef __usbconfig_h_included__ |
#define __usbconfig_h_included__ |
/* |
General Description: |
This file contains parts of the USB driver which can be configured and can or |
must be adapted to your hardware. |
*/ |
/* ---------------------------- Hardware Config ---------------------------- */ |
#if! defined (__AVR_ATtiny45__) |
#define USB_CFG_IOPORTNAME C |
/* This is the port where the USB bus is connected. When you configure it to |
* "PORTB", the registers PORTB, PINB (=PORTB+2) and DDRB (=PORTB+1) will be |
* used. |
*/ |
#define USB_CFG_DMINUS_BIT 0 |
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. |
* This MUST be bit 0. All other values will result in a compile error! |
*/ |
#define USB_CFG_DPLUS_BIT 1 |
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. |
* This may be any bit in the port. Please note that D+ must also be connected |
* to interrupt pin INT0! |
*/ |
#else |
#define USB_CFG_IOPORTNAME B |
#define USB_CFG_DMINUS_BIT 0 |
#define USB_CFG_DPLUS_BIT 2 |
#endif |
/* --------------------------- Functional Range ---------------------------- */ |
#define USB_CFG_HAVE_INTRIN_ENDPOINT 0 |
/* Define this to 1 if you want to compile a version with two endpoints: The |
* default control endpoint 0 and an interrupt-in endpoint 1. |
*/ |
#define USB_CFG_INTR_POLL_INTERVAL 10 |
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll |
* interval. The value is in milliseconds and must not be less than 10 ms for |
* low speed devices. |
*/ |
#define USB_CFG_IS_SELF_POWERED 0 |
/* Define this to 1 if the device has its own power supply. Set it to 0 if the |
* device is powered from the USB bus. |
*/ |
#define USB_CFG_MAX_BUS_POWER 10 |
/* Set this variable to the maximum USB bus power consumption of your device. |
* The value is in milliamperes. [It will be divided by two since USB |
* communicates power requirements in units of 2 mA.] |
*/ |
#define USB_CFG_SAMPLE_EXACT 1 |
/* This variable affects Sampling Jitter for USB receiving. When it is 0, the |
* driver guarantees a sampling window of 1/2 bit. The USB spec requires |
* that the receiver has at most 1/4 bit sampling window. The 1/2 bit window |
* should still work reliably enough because we work at low speed. If you want |
* to meet the spec, set this value to 1. This will unroll a loop which |
* results in bigger code size. |
* If you have problems with long cables, try setting this value to 1. |
*/ |
#define USB_CFG_IMPLEMENT_FN_WRITE 1 |
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out |
* transfers. Set it to 0 if you don't need it and want to save a couple of |
* bytes. |
*/ |
#define USB_CFG_IMPLEMENT_FN_READ 1 |
/* Set this to 1 if you need to send control replies which are generated |
* "on the fly" when usbFunctionRead() is called. If you only want to send |
* data from a static buffer, set it to 0 and return the data from |
* usbFunctionSetup(). This saves a couple of bytes. |
*/ |
/* -------------------------- Device Description --------------------------- */ |
#define USB_CFG_VENDOR_ID 0x03, 0x04 |
/* USB vendor ID for the device, low byte first. */ |
#define USB_CFG_DEVICE_ID 0x31, 0xc6 |
/* This is the ID of the device, low byte first. It is interpreted in the |
* scope of the vendor ID. The only requirement is that no two devices may |
* share the same product and vendor IDs. Not even if the devices are never |
* on the same bus together! |
*/ |
#define USB_CFG_DEVICE_VERSION 0x05, 0x01 |
/* Version number of the device: Minor number first, then major number. |
*/ |
#define USB_CFG_VENDOR_NAME 'T', 'i', 'l', 'l', ' ', 'H', 'a', 'r', 'b', 'a', 'u', 'm' |
#define USB_CFG_VENDOR_NAME_LEN 12 |
/* These two values define the vendor name returned by the USB device. The name |
* must be given as a list of characters under single quotes. The characters |
* are interpreted as Unicode (UTF-16) entities. |
* If you don't want a vendor name string, undefine these macros. |
*/ |
#define USB_CFG_DEVICE_NAME 'i','2','c','-','t','i','n','y','-','u','s','b' |
#define USB_CFG_DEVICE_NAME_LEN 12 |
/* Same as above for the device name. If you don't want a device name, undefine |
* the macros. |
*/ |
#define USB_CFG_DEVICE_CLASS 0xff |
#define USB_CFG_DEVICE_SUBCLASS 0 |
/* See USB specification if you want to conform to an existing device class. |
*/ |
#define USB_CFG_INTERFACE_CLASS 0 |
#define USB_CFG_INTERFACE_SUBCLASS 0 |
#define USB_CFG_INTERFACE_PROTOCOL 0 |
/* See USB specification if you want to conform to an existing device class or |
* protocol. |
*/ |
#endif /* __usbconfig_h_included__ */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/Changelog.txt |
---|
0,0 → 1,134 |
This file documents changes in the firmware-only USB driver for atmel's AVR |
microcontrollers. New entries are always appended to the end of the file. |
Scroll down to the bottom to see the most recent changes. |
2005-04-01: |
- Implemented endpoint 1 as interrupt-in endpoint. |
- Moved all configuration options to usbconfig.h which is not part of the |
driver. |
- Changed interface for usbVendorSetup(). |
- Fixed compatibility with ATMega8 device. |
- Various minor optimizations. |
2005-04-11: |
- Changed interface to application: Use usbFunctionSetup(), usbFunctionRead() |
and usbFunctionWrite() now. Added configuration options to choose which |
of these functions to compile in. |
- Assembler module delivers receive data non-inverted now. |
- Made register and bit names compatible with more AVR devices. |
2005-05-03: |
- Allow address of usbRxBuf on any memory page as long as the buffer does |
not cross 256 byte page boundaries. |
- Better device compatibility: works with Mega88 now. |
- Code optimization in debugging module. |
- Documentation updates. |
2006-01-02: |
- Added (free) default Vendor- and Product-IDs bought from voti.nl. |
- Added USBID-License.txt file which defines the rules for using the free |
shared VID/PID pair. |
- Added Readme.txt to the usbdrv directory which clarifies administrative |
issues. |
2006-01-25: |
- Added "configured state" to become more standards compliant. |
- Added "HALT" state for interrupt endpoint. |
- Driver passes the "USB Command Verifier" test from usb.org now. |
- Made "serial number" a configuration option. |
- Minor optimizations, we now recommend compiler option "-Os" for best |
results. |
- Added a version number to usbdrv.h |
2006-02-03: |
- New configuration variable USB_BUFFER_SECTION for the memory section where |
the USB rx buffer will go. This defaults to ".bss" if not defined. Since |
this buffer MUST NOT cross 256 byte pages (not even touch a page at the |
end), the user may want to pass a linker option similar to |
"-Wl,--section-start=.mybuffer=0x800060". |
- Provide structure for usbRequest_t. |
- New defines for USB constants. |
- Prepared for HID implementations. |
- Increased data size limit for interrupt transfers to 8 bytes. |
- New macro usbInterruptIsReady() to query interrupt buffer state. |
2006-02-18: |
- Ensure that the data token which is sent as an ack to an OUT transfer is |
always zero sized. This fixes a bug where the host reports an error after |
sending an out transfer to the device, although all data arrived at the |
device. |
- Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite(). |
* Release 2006-02-20 |
- Give a compiler warning when compiling with debugging turned on. |
- Added Oleg Semyonov's changes for IAR-cc compatibility. |
- Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect() |
(also thanks to Oleg!). |
- Rearranged tests in usbPoll() to save a couple of instructions in the most |
likely case that no actions are pending. |
- We need a delay between the SET ADDRESS request until the new address |
becomes active. This delay was handled in usbPoll() until now. Since the |
spec says that the delay must not exceed 2ms, previous versions required |
aggressive polling during the enumeration phase. We have now moved the |
handling of the delay into the interrupt routine. |
- We must not reply with NAK to a SETUP transaction. We can only achieve this |
by making sure that the rx buffer is empty when SETUP tokens are expected. |
We therefore don't pass zero sized data packets from the status phase of |
a transfer to usbPoll(). This change MAY cause troubles if you rely on |
receiving a less than 8 bytes long packet in usbFunctionWrite() to |
identify the end of a transfer. usbFunctionWrite() will NEVER be called |
with a zero length. |
* Release 2006-03-14 |
- Improved IAR C support: tiny memory model, more devices |
- Added template usbconfig.h file under the name usbconfig-prototype.h |
* Release 2006-03-26 |
- Added provision for one more interrupt-in endpoint (endpoint 3). |
- Added provision for one interrupt-out endpoint (endpoint 1). |
- Added flowcontrol macros for USB. |
- Added provision for custom configuration descriptor. |
- Allow ANY two port bits for D+ and D-. |
- Merged (optional) receive endpoint number into global usbRxToken variable. |
- Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the |
variable name from the single port letter instead of computing the address |
of related ports from the output-port address. |
* Release 2006-06-26 |
- Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the |
new features. |
- Removed "#warning" directives because IAR does not understand them. Use |
unused static variables instead to generate a warning. |
- Do not include <avr/io.h> when compiling with IAR. |
- Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each |
USB descriptor should be handled. It is now possible to provide descriptor |
data in Flash, RAM or dynamically at runtime. |
- STALL is now a status in usbTxLen* instead of a message. We can now conform |
to the spec and leave the stall status pending until it is cleared. |
- Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the |
application code to reset data toggling on interrupt pipes. |
* Release 2006-07-18 |
- Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes |
an assembler error. |
- usbDeviceDisconnect() takes pull-up resistor to high impedance now. |
* Release 2007-02-01 |
- Merged in some code size improvements from usbtiny (thanks to Dick |
Streefland for these optimizations!) |
- Special alignment requirement for usbRxBuf not required any more. Thanks |
again to Dick Streefland for this hint! |
- Reverted to "#warning" instead of unused static variables -- new versions |
of IAR CC should handle this directive. |
- Changed Open Source license to GNU GPL v2 in order to make linking against |
other free libraries easier. We no longer require publication of the |
circuit diagrams, but we STRONGLY encourage it. If you improve the driver |
itself, PLEASE grant us a royalty free license to your changes for our |
commercial license. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/CommercialLicense.txt |
---|
0,0 → 1,155 |
AVR-USB Driver Software License Agreement |
Version 2006-07-24 |
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN |
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING |
THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT. |
1 DEFINITIONS |
1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH, |
Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA. |
1.2 "You" shall mean the Licensee. |
1.3 "AVR-USB" shall mean the firmware-only USB device implementation for |
Atmel AVR microcontrollers distributed by OBJECTIVE DEVELOPMENT and |
consisting of the files usbdrv.c, usbdrv.h, usbdrvasm.S, oddebug.c, |
oddebug.h, usbdrvasm.asm, iarcompat.h and usbconfig-prototype.h. |
2 LICENSE GRANTS |
2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source |
code of AVR-USB. |
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the |
non-exclusive right to use and distribute AVR-USB with your hardware |
product(s), restricted by the limitations in section 3 below. |
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify |
your copy of AVR-USB according to your needs. |
2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use |
USB Product ID(s) sent to you in e-mail after receiving your payment in |
conjunction with USB Vendor ID 5824. OBJECTIVE DEVELOPMENT has acquired an |
exclusive license for this pair of USB identifiers from Wouter van Ooijen |
(www.voti.nl), who has licensed the VID from the USB Implementers Forum, |
Inc. (www.usb.org). |
3 LICENSE RESTRICTIONS |
3.1 Number of Units. Only one of the following three definitions is |
applicable. Which one is determined by the amount you pay to OBJECTIVE |
DEVELOPMENT, see section 4 ("Payment") below. |
Hobby License: You may use AVR-USB according to section 2 above in no more |
than 5 hardware units. These units must not be sold for profit. |
Entry Level License: You may use AVR-USB according to section 2 above in no |
more than 150 hardware units. |
Professional License: You may use AVR-USB according to section 2 above in |
any number of hardware units, except for large scale production ("unlimited |
fair use"). Quantities below 10,000 units are not considered large scale |
production. If your reach quantities which are obviously large scale |
production, you must pay a license fee of 0.10 EUR per unit for all units |
above 10,000. |
3.2 Rental. You may not rent, lease, or lend AVR-USB or otherwise encumber |
any copy of AVR-USB, or any of the rights granted herein. |
3.3 Transfer. You may not transfer your rights under this Agreement to |
another party without OBJECTIVE DEVELOPMENT's prior written consent. If |
such consent is obtained, you may permanently transfer this License to |
another party. The recipient of such transfer must agree to all terms and |
conditions of this Agreement. |
3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not |
expressly granted. |
3.5 Non-Exclusive Rights. Your license rights under this Agreement are |
non-exclusive. |
3.6 Third Party Rights. This Agreement cannot grant you rights controlled |
by third parties. In particular, you are not allowed to use the USB logo or |
other trademarks owned by the USB Implementers Forum, Inc. without their |
consent. Since such consent depends on USB certification, it should be |
noted that AVR-USB will not pass certification because it does not |
implement checksum verification and the microcontroller ports do not meet |
the electrical specifications. |
4 PAYMENT |
The payment amount depends on the variation of this agreement (according to |
section 3.1) into which you want to enter. Concrete prices are listed on |
OBJECTIVE DEVELOPMENT's web site, usually at |
http://www.obdev.at/avrusb/license.html. You agree to pay the amount listed |
there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor |
or reseller. |
5 COPYRIGHT AND OWNERSHIP |
AVR-USB is protected by copyright laws and international copyright |
treaties, as well as other intellectual property laws and treaties. AVR-USB |
is licensed, not sold. |
6 TERM AND TERMINATION |
6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE |
DEVELOPMENT may terminate this Agreement and revoke the granted license and |
USB-IDs if you fail to comply with any of its terms and conditions. |
6.2 Survival of Terms. All provisions regarding secrecy, confidentiality |
and limitation of liability shall survive termination of this agreement. |
7 DISCLAIMER OF WARRANTY AND LIABILITY |
LIMITED WARRANTY. AVR-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE |
DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER |
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND |
NON-INFRINGEMENT, WITH REGARD TO AVR-USB, AND THE PROVISION OF OR FAILURE |
TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL |
RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO |
STATE/JURISDICTION. |
LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, |
IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY |
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER |
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, |
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY |
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE AVR-USB OR THE |
PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE |
DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY |
CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS |
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR AVR-USB. |
8 MISCELLANEOUS TERMS |
8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing |
purposes that you entered into this agreement. |
8.2 Entire Agreement. This document represents the entire agreement between |
OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by |
an authorized representative of both, OBJECTIVE DEVELOPMENT and you. |
8.3 Severability. In case a provision of these terms and conditions should |
be or become partly or entirely invalid, ineffective, or not executable, |
the validity of all other provisions shall not be affected. |
8.4 Applicable Law. This agreement is governed by the laws of the Republic |
of Austria. |
8.5 Responsible Courts. The responsible courts in Vienna/Austria will have |
exclusive jurisdiction regarding all disputes in connection with this |
agreement. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/License.txt |
---|
0,0 → 1,359 |
OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the |
terms and conditions of the GNU GPL version 2, see the text below. In addition |
to the requirements in the GPL, we STRONGLY ENCOURAGE you to do the following: |
(1) Publish your entire project on a web site and drop us a note with the URL. |
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission. |
(2) Adhere to minimum publication standards. Please include AT LEAST: |
- a circuit diagram in PDF, PNG or GIF format |
- full source code for the host software |
- a Readme.txt file in ASCII format which describes the purpose of the |
project and what can be found in which directories and which files |
- a reference to http://www.obdev.at/avrusb/ |
(3) If you improve the driver firmware itself, please give us a free license |
to your modifications for our commercial license offerings. |
GNU GENERAL PUBLIC LICENSE |
Version 2, June 1991 |
Copyright (C) 1989, 1991 Free Software Foundation, Inc. |
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
Preamble |
The licenses for most software are designed to take away your |
freedom to share and change it. By contrast, the GNU General Public |
License is intended to guarantee your freedom to share and change free |
software--to make sure the software is free for all its users. This |
General Public License applies to most of the Free Software |
Foundation's software and to any other program whose authors commit to |
using it. (Some other Free Software Foundation software is covered by |
the GNU Library General Public License instead.) You can apply it to |
your programs, too. |
When we speak of free software, we are referring to freedom, not |
price. Our General Public Licenses are designed to make sure that you |
have the freedom to distribute copies of free software (and charge for |
this service if you wish), that you receive source code or can get it |
if you want it, that you can change the software or use pieces of it |
in new free programs; and that you know you can do these things. |
To protect your rights, we need to make restrictions that forbid |
anyone to deny you these rights or to ask you to surrender the rights. |
These restrictions translate to certain responsibilities for you if you |
distribute copies of the software, or if you modify it. |
For example, if you distribute copies of such a program, whether |
gratis or for a fee, you must give the recipients all the rights that |
you have. You must make sure that they, too, receive or can get the |
source code. And you must show them these terms so they know their |
rights. |
We protect your rights with two steps: (1) copyright the software, and |
(2) offer you this license which gives you legal permission to copy, |
distribute and/or modify the software. |
Also, for each author's protection and ours, we want to make certain |
that everyone understands that there is no warranty for this free |
software. If the software is modified by someone else and passed on, we |
want its recipients to know that what they have is not the original, so |
that any problems introduced by others will not reflect on the original |
authors' reputations. |
Finally, any free program is threatened constantly by software |
patents. We wish to avoid the danger that redistributors of a free |
program will individually obtain patent licenses, in effect making the |
program proprietary. To prevent this, we have made it clear that any |
patent must be licensed for everyone's free use or not licensed at all. |
The precise terms and conditions for copying, distribution and |
modification follow. |
GNU GENERAL PUBLIC LICENSE |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
0. This License applies to any program or other work which contains |
a notice placed by the copyright holder saying it may be distributed |
under the terms of this General Public License. The "Program", below, |
refers to any such program or work, and a "work based on the Program" |
means either the Program or any derivative work under copyright law: |
that is to say, a work containing the Program or a portion of it, |
either verbatim or with modifications and/or translated into another |
language. (Hereinafter, translation is included without limitation in |
the term "modification".) Each licensee is addressed as "you". |
Activities other than copying, distribution and modification are not |
covered by this License; they are outside its scope. The act of |
running the Program is not restricted, and the output from the Program |
is covered only if its contents constitute a work based on the |
Program (independent of having been made by running the Program). |
Whether that is true depends on what the Program does. |
1. You may copy and distribute verbatim copies of the Program's |
source code as you receive it, in any medium, provided that you |
conspicuously and appropriately publish on each copy an appropriate |
copyright notice and disclaimer of warranty; keep intact all the |
notices that refer to this License and to the absence of any warranty; |
and give any other recipients of the Program a copy of this License |
along with the Program. |
You may charge a fee for the physical act of transferring a copy, and |
you may at your option offer warranty protection in exchange for a fee. |
2. You may modify your copy or copies of the Program or any portion |
of it, thus forming a work based on the Program, and copy and |
distribute such modifications or work under the terms of Section 1 |
above, provided that you also meet all of these conditions: |
a) You must cause the modified files to carry prominent notices |
stating that you changed the files and the date of any change. |
b) You must cause any work that you distribute or publish, that in |
whole or in part contains or is derived from the Program or any |
part thereof, to be licensed as a whole at no charge to all third |
parties under the terms of this License. |
c) If the modified program normally reads commands interactively |
when run, you must cause it, when started running for such |
interactive use in the most ordinary way, to print or display an |
announcement including an appropriate copyright notice and a |
notice that there is no warranty (or else, saying that you provide |
a warranty) and that users may redistribute the program under |
these conditions, and telling the user how to view a copy of this |
License. (Exception: if the Program itself is interactive but |
does not normally print such an announcement, your work based on |
the Program is not required to print an announcement.) |
These requirements apply to the modified work as a whole. If |
identifiable sections of that work are not derived from the Program, |
and can be reasonably considered independent and separate works in |
themselves, then this License, and its terms, do not apply to those |
sections when you distribute them as separate works. But when you |
distribute the same sections as part of a whole which is a work based |
on the Program, the distribution of the whole must be on the terms of |
this License, whose permissions for other licensees extend to the |
entire whole, and thus to each and every part regardless of who wrote it. |
Thus, it is not the intent of this section to claim rights or contest |
your rights to work written entirely by you; rather, the intent is to |
exercise the right to control the distribution of derivative or |
collective works based on the Program. |
In addition, mere aggregation of another work not based on the Program |
with the Program (or with a work based on the Program) on a volume of |
a storage or distribution medium does not bring the other work under |
the scope of this License. |
3. You may copy and distribute the Program (or a work based on it, |
under Section 2) in object code or executable form under the terms of |
Sections 1 and 2 above provided that you also do one of the following: |
a) Accompany it with the complete corresponding machine-readable |
source code, which must be distributed under the terms of Sections |
1 and 2 above on a medium customarily used for software interchange; or, |
b) Accompany it with a written offer, valid for at least three |
years, to give any third party, for a charge no more than your |
cost of physically performing source distribution, a complete |
machine-readable copy of the corresponding source code, to be |
distributed under the terms of Sections 1 and 2 above on a medium |
customarily used for software interchange; or, |
c) Accompany it with the information you received as to the offer |
to distribute corresponding source code. (This alternative is |
allowed only for noncommercial distribution and only if you |
received the program in object code or executable form with such |
an offer, in accord with Subsection b above.) |
The source code for a work means the preferred form of the work for |
making modifications to it. For an executable work, complete source |
code means all the source code for all modules it contains, plus any |
associated interface definition files, plus the scripts used to |
control compilation and installation of the executable. However, as a |
special exception, the source code distributed need not include |
anything that is normally distributed (in either source or binary |
form) with the major components (compiler, kernel, and so on) of the |
operating system on which the executable runs, unless that component |
itself accompanies the executable. |
If distribution of executable or object code is made by offering |
access to copy from a designated place, then offering equivalent |
access to copy the source code from the same place counts as |
distribution of the source code, even though third parties are not |
compelled to copy the source along with the object code. |
4. You may not copy, modify, sublicense, or distribute the Program |
except as expressly provided under this License. Any attempt |
otherwise to copy, modify, sublicense or distribute the Program is |
void, and will automatically terminate your rights under this License. |
However, parties who have received copies, or rights, from you under |
this License will not have their licenses terminated so long as such |
parties remain in full compliance. |
5. You are not required to accept this License, since you have not |
signed it. However, nothing else grants you permission to modify or |
distribute the Program or its derivative works. These actions are |
prohibited by law if you do not accept this License. Therefore, by |
modifying or distributing the Program (or any work based on the |
Program), you indicate your acceptance of this License to do so, and |
all its terms and conditions for copying, distributing or modifying |
the Program or works based on it. |
6. Each time you redistribute the Program (or any work based on the |
Program), the recipient automatically receives a license from the |
original licensor to copy, distribute or modify the Program subject to |
these terms and conditions. You may not impose any further |
restrictions on the recipients' exercise of the rights granted herein. |
You are not responsible for enforcing compliance by third parties to |
this License. |
7. If, as a consequence of a court judgment or allegation of patent |
infringement or for any other reason (not limited to patent issues), |
conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot |
distribute so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you |
may not distribute the Program at all. For example, if a patent |
license would not permit royalty-free redistribution of the Program by |
all those who receive copies directly or indirectly through you, then |
the only way you could satisfy both it and this License would be to |
refrain entirely from distribution of the Program. |
If any portion of this section is held invalid or unenforceable under |
any particular circumstance, the balance of the section is intended to |
apply and the section as a whole is intended to apply in other |
circumstances. |
It is not the purpose of this section to induce you to infringe any |
patents or other property right claims or to contest validity of any |
such claims; this section has the sole purpose of protecting the |
integrity of the free software distribution system, which is |
implemented by public license practices. Many people have made |
generous contributions to the wide range of software distributed |
through that system in reliance on consistent application of that |
system; it is up to the author/donor to decide if he or she is willing |
to distribute software through any other system and a licensee cannot |
impose that choice. |
This section is intended to make thoroughly clear what is believed to |
be a consequence of the rest of this License. |
8. If the distribution and/or use of the Program is restricted in |
certain countries either by patents or by copyrighted interfaces, the |
original copyright holder who places the Program under this License |
may add an explicit geographical distribution limitation excluding |
those countries, so that distribution is permitted only in or among |
countries not thus excluded. In such case, this License incorporates |
the limitation as if written in the body of this License. |
9. The Free Software Foundation may publish revised and/or new versions |
of the General Public License from time to time. Such new versions will |
be similar in spirit to the present version, but may differ in detail to |
address new problems or concerns. |
Each version is given a distinguishing version number. If the Program |
specifies a version number of this License which applies to it and "any |
later version", you have the option of following the terms and conditions |
either of that version or of any later version published by the Free |
Software Foundation. If the Program does not specify a version number of |
this License, you may choose any version ever published by the Free Software |
Foundation. |
10. If you wish to incorporate parts of the Program into other free |
programs whose distribution conditions are different, write to the author |
to ask for permission. For software which is copyrighted by the Free |
Software Foundation, write to the Free Software Foundation; we sometimes |
make exceptions for this. Our decision will be guided by the two goals |
of preserving the free status of all derivatives of our free software and |
of promoting the sharing and reuse of software generally. |
NO WARRANTY |
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
REPAIR OR CORRECTION. |
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGES. |
END OF TERMS AND CONDITIONS |
How to Apply These Terms to Your New Programs |
If you develop a new program, and you want it to be of the greatest |
possible use to the public, the best way to achieve this is to make it |
free software which everyone can redistribute and change under these terms. |
To do so, attach the following notices to the program. It is safest |
to attach them to the start of each source file to most effectively |
convey the exclusion of warranty; and each file should have at least |
the "copyright" line and a pointer to where the full notice is found. |
<one line to give the program's name and a brief idea of what it does.> |
Copyright (C) <year> <name of author> |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Also add information on how to contact you by electronic and paper mail. |
If the program is interactive, make it output a short notice like this |
when it starts in an interactive mode: |
Gnomovision version 69, Copyright (C) year name of author |
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
This is free software, and you are welcome to redistribute it |
under certain conditions; type `show c' for details. |
The hypothetical commands `show w' and `show c' should show the appropriate |
parts of the General Public License. Of course, the commands you use may |
be called something other than `show w' and `show c'; they could even be |
mouse-clicks or menu items--whatever suits your program. |
You should also get your employer (if you work as a programmer) or your |
school, if any, to sign a "copyright disclaimer" for the program, if |
necessary. Here is a sample; alter the names: |
Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
`Gnomovision' (which makes passes at compilers) written by James Hacker. |
<signature of Ty Coon>, 1 April 1989 |
Ty Coon, President of Vice |
This General Public License does not permit incorporating your program into |
proprietary programs. If your program is a subroutine library, you may |
consider it more useful to permit linking proprietary applications with the |
library. If this is what you want to do, use the GNU Library General |
Public License instead of this License. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/Readme.txt |
---|
0,0 → 1,84 |
This is the Readme file to Objective Development's firmware-only USB driver |
for Atmel AVR microcontrollers. For more information please visit |
http://www.obdev.at/avrusb/ |
This directory contains the USB firmware only. Copy it as-is to your own |
project and add your own version of "usbconfig.h". A template for your own |
"usbconfig.h" can be found in "usbconfig-prototype.h" in this directory. |
TECHNICAL DOCUMENTATION |
======================= |
The technical documentation for the firmware driver is contained in the file |
"usbdrv.h". Please read all of it carefully! |
USB IDENTIFIERS |
=============== |
Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs |
are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you |
can assign PIDs at will. |
Since an entry level cost of 1,500 USD is too high for most small companies |
and hobbyists, we provide a single VID/PID pair for free. If you want to use |
your own VID and PID instead of our's, define the macros "USB_CFG_VENDOR_ID" |
and "USB_CFG_DEVICE_ID" accordingly in "usbconfig.h". |
To use our predefined VID/PID pair, you MUST conform to a couple of |
requirements. See the file "USBID-License.txt" for details. |
Objective Development also has some offerings which include product IDs. See |
http://www.obdev.at/avrusb/ for details. |
HOST DRIVER |
=========== |
You have received this driver together with an example device implementation |
and an example host driver. The host driver is based on libusb and compiles |
on various Unix flavors (Linux, BSD, Mac OS X). It also compiles natively on |
Windows using MinGW (see www.mingw.org) and libusb-win32 (see |
libusb-win32.sourceforge.net). The "Automator" project contains a native |
Windows host driver (not based on libusb) for Human Interface Devices. |
DEVELOPMENT SYSTEM |
================== |
This driver has been developed and optimized for the GNU compiler version 3 |
(gcc 3). It does work well with gcc 4 and future versions will probably be |
optimized for gcc 4. We recommend that you use the GNU compiler suite because |
it is freely available. AVR-USB has also been ported to the IAR compiler and |
assembler. It has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 |
with the "small" and "tiny" memory model. Please note that gcc is more |
efficient for usbdrv.c because this module has been deliberately optimized |
for gcc. |
USING AVR-USB FOR FREE |
====================== |
The AVR firmware driver is published under the GNU General Public License |
Version 2 (GPL2). See the file "License.txt" for details. |
If you decide for the free GPL2, we STRONGLY ENCOURAGE you to do the following |
things IN ADDITION to the obligations from the GPL2: |
(1) Publish your entire project on a web site and drop us a note with the URL. |
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission. |
(2) Adhere to minimum publication standards. Please include AT LEAST: |
- a circuit diagram in PDF, PNG or GIF format |
- full source code for the host software |
- a Readme.txt file in ASCII format which describes the purpose of the |
project and what can be found in which directories and which files |
- a reference to http://www.obdev.at/avrusb/ |
(3) If you improve the driver firmware itself, please give us a free license |
to your modifications for our commercial license offerings. |
COMMERCIAL LICENSES FOR AVR-USB |
=============================== |
If you don't want to publish your source code under the terms of the GPL2, |
you can simply pay money for AVR-USB. As an additional benefit you get |
USB PIDs for free, licensed exclusively to you. See the file |
"CommercialLicense.txt" for details. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/USBID-License.txt |
---|
0,0 → 1,143 |
Royalty-Free Non-Exclusive License USB Product-ID |
================================================= |
Version 2006-06-19 |
OBJECTIVE DEVELOPMENT Software GmbH hereby grants you the non-exclusive |
right to use three USB.org vendor-ID (VID) / product-ID (PID) pairs with |
products based on Objective Development's firmware-only USB driver for |
Atmel AVR microcontrollers: |
* VID = 5824 (=0x16c0) / PID = 1500 (=0x5dc) for devices implementing no |
USB device class (vendor-class devices with USB class = 0xff). Devices |
using this pair will be referred to as "VENDOR CLASS" devices. |
* VID = 5824 (=0x16c0) / PID = 1503 (=0x5df) for HID class devices |
(excluding mice and keyboards). Devices using this pair will be referred |
to as "HID CLASS" devices. |
* VID = 5824 (=0x16c0) / PID = 1505 (=0x5e1) for CDC class modem devices |
Devices using this pair will be referred to as "CDC-ACM CLASS" devices. |
Since the granted right is non-exclusive, the same VID/PID pairs may be |
used by many companies and individuals for different products. To avoid |
conflicts, your device and host driver software MUST adhere to the rules |
outlined below. |
OBJECTIVE DEVELOPMENT Software GmbH has licensed these VID/PID pairs from |
Wouter van Ooijen (see www.voti.nl), who has licensed the VID from the USB |
Implementers Forum, Inc. (see www.usb.org). The VID is registered for the |
company name "Van Ooijen Technische Informatica". |
RULES AND RESTRICTIONS |
====================== |
(1) The USB device MUST provide a textual representation of the |
manufacturer and product identification. The manufacturer identification |
MUST be available at least in USB language 0x0409 (English/US). |
(2) The textual manufacturer identification MUST contain either an Internet |
domain name (e.g. "mycompany.com") registered and owned by you, or an |
e-mail address under your control (e.g. "myname@gmx.net"). You can embed |
the domain name or e-mail address in any string you like, e.g. "Objective |
Development http://www.obdev.at/avrusb/". |
(3) You are responsible for retaining ownership of the domain or e-mail |
address for as long as any of your products are in use. |
(4) You may choose any string for the textual product identification, as |
long as this string is unique within the scope of your textual manufacturer |
identification. |
(5) Matching of device-specific drivers MUST be based on the textual |
manufacturer and product identification in addition to the usual VID/PID |
matching. This means that operating system features which are based on |
VID/PID matching only (e.g. Windows kernel level drivers, automatic actions |
when the device is plugged in etc) MUST NOT be used. The driver matching |
MUST be a comparison of the entire strings, NOT a sub-string match. For |
CDC-ACM CLASS devices, a generic class driver should be used and the |
matching is based on the USB device class. |
(6) The extent to which VID/PID matching is allowed for non device-specific |
drivers or features depends on the operating system and particular VID/PID |
pair used: |
* Mac OS X, Linux, FreeBSD and other Unixes: No VID/PID matching is |
required and hence no VID/PID-only matching is allowed at all. |
* Windows: The operating system performs VID/PID matching for the kernel |
level driver. You are REQUIRED to use libusb-win32 (see |
http://libusb-win32.sourceforge.net/) as the kernel level driver for |
VENDOR CLASS devices. HID CLASS devices all use the generic HID class |
driver shipped with Windows, except mice and keyboards. You therefore |
MUST NOT use any of the shared VID/PID pairs for mice or keyboards. |
CDC-ACM CLASS devices require a ".inf" file which matches on the VID/PID |
pair. This ".inf" file MUST load the "usbser" driver to configure the |
device as modem (COM-port). |
(7) OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any |
problems which are caused by the shared use of these VID/PID pairs. You |
have been warned that the sharing of VID/PID pairs may cause problems. If |
you want to avoid them, get your own VID/PID pair for exclusive use. |
HOW TO IMPLEMENT THESE RULES |
============================ |
The following rules are for VENDOR CLASS and HID CLASS devices. CDC-ACM |
CLASS devices use the operating system's class driver and don't need a |
custom driver. |
The host driver MUST iterate over all devices with the given VID/PID |
numbers in their device descriptors and query the string representation for |
the manufacturer name in USB language 0x0409 (English/US). It MUST compare |
the ENTIRE string with your textual manufacturer identification chosen in |
(2) above. A substring search for your domain or e-mail address is NOT |
acceptable. The driver MUST NOT touch the device (other than querying the |
descriptors) unless the strings match. |
For all USB devices with matching VID/PID and textual manufacturer |
identification, the host driver must query the textual product |
identification and string-compare it with the name of the product it can |
control. It may only initialize the device if the product matches exactly. |
Objective Development provides examples for these matching rules with the |
"PowerSwitch" project (using libusb) and with the "Automator" project |
(using Windows calls on Windows and libusb on Unix). |
Technical Notes: |
================ |
Sharing the same VID/PID pair among devices is possible as long as ALL |
drivers which match the VID/PID also perform matching on the textual |
identification strings. This is easy on all operating systems except |
Windows, since Windows establishes a static connection between the VID/PID |
pair and a kernel level driver. All devices with the same VID/PID pair must |
therefore use THE SAME kernel level driver. |
We therefore demand that you use libusb-win32 for VENDOR CLASS devices. |
This is a generic kernel level driver which allows all types of USB access |
for user space applications. This is only a partial solution of the |
problem, though, because different device drivers may come with different |
versions of libusb-win32 and they may not work with the libusb version of |
the respective other driver. You are therefore encouraged to test your |
driver against a broad range of libusb-win32 versions. Do not use new |
features in new versions, or check for their existence before you use them. |
When a new libusb-win32 becomes available, make sure that your driver is |
compatible with it. |
For HID CLASS devices it is necessary that all those devices bind to the |
same kernel driver: Microsoft's generic USB HID driver. This is true for |
all HID devices except those with a specialized driver. Currently, the only |
HIDs with specialized drivers are mice and keyboards. You therefore MUST |
NOT use a shared VID/PID with mouse and keyboard devices. |
Sharing the same VID/PID among different products is unusual and probably |
violates the USB specification. If you do it, you do it at your own risk. |
To avoid possible incompatibilities, we highly recommend that you get your |
own VID/PID pair if you intend to sell your product. Objective |
Development's commercial licenses for AVR-USB include a PID for |
unrestricted exclusive use. |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/iarcompat.h |
---|
0,0 → 1,70 |
/* Name: iarcompat.h |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2006-03-01 |
* Tabsize: 4 |
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: iarcompat.h,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
/* |
General Description: |
This header is included when we compile with the IAR C-compiler and assembler. |
It defines macros for cross compatibility between gcc and IAR-cc. |
Thanks to Oleg Semyonov for his help with the IAR tools port! |
*/ |
#ifndef __iarcompat_h_INCLUDED__ |
#define __iarcompat_h_INCLUDED__ |
#if defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ |
/* Enable bit definitions */ |
#ifndef ENABLE_BIT_DEFINITIONS |
# define ENABLE_BIT_DEFINITIONS 1 |
#endif |
/* Include IAR headers */ |
#include <ioavr.h> |
#ifndef __IAR_SYSTEMS_ASM__ |
# include <inavr.h> |
#endif |
#define __attribute__(arg) |
#define IAR_SECTION(section) @ section |
#ifndef USB_BUFFER_SECTION |
# define USB_BUFFER_SECTION "TINY_Z" /* if user has not selected a named section */ |
#endif |
#ifdef __IAR_SYSTEMS_ASM__ |
# define __ASSEMBLER__ |
#endif |
#ifdef __HAS_ELPM__ |
# define PROGMEM __farflash |
#else |
# define PROGMEM __flash |
#endif |
#define PRG_RDB(addr) (*(PROGMEM char *)(addr)) |
/* The following definitions are not needed by the driver, but may be of some |
* help if you port a gcc based project to IAR. |
*/ |
#define cli() __disable_interrupt() |
#define sei() __enable_interrupt() |
#define wdt_reset() __watchdog_reset() |
/* Depending on the device you use, you may get problems with the way usbdrv.h |
* handles the differences between devices. Since IAR does not use #defines |
* for MCU registers, we can't check for the existence of a particular |
* register with an #ifdef. If the autodetection mechanism fails, include |
* definitions for the required USB_INTR_* macros in your usbconfig.h. See |
* usbconfig-prototype.h and usbdrv.h for details. |
*/ |
#endif /* defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ */ |
#endif /* __iarcompat_h_INCLUDED__ */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/oddebug.c |
---|
0,0 → 1,50 |
/* Name: oddebug.c |
* Project: AVR library |
* Author: Christian Starkjohann |
* Creation Date: 2005-01-16 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: oddebug.c,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
#include "oddebug.h" |
#if DEBUG_LEVEL > 0 |
#warning "Never compile production devices with debugging enabled" |
static void uartPutc(char c) |
{ |
while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */ |
ODDBG_UDR = c; |
} |
static uchar hexAscii(uchar h) |
{ |
h &= 0xf; |
if(h >= 10) |
h += 'a' - (uchar)10 - '0'; |
h += '0'; |
return h; |
} |
static void printHex(uchar c) |
{ |
uartPutc(hexAscii(c >> 4)); |
uartPutc(hexAscii(c)); |
} |
void odDebug(uchar prefix, uchar *data, uchar len) |
{ |
printHex(prefix); |
uartPutc(':'); |
while(len--){ |
uartPutc(' '); |
printHex(*data++); |
} |
uartPutc('\r'); |
uartPutc('\n'); |
} |
#endif |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/oddebug.h |
---|
0,0 → 1,126 |
/* Name: oddebug.h |
* Project: AVR library |
* Author: Christian Starkjohann |
* Creation Date: 2005-01-16 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: oddebug.h,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
#ifndef __oddebug_h_included__ |
#define __oddebug_h_included__ |
/* |
General Description: |
This module implements a function for debug logs on the serial line of the |
AVR microcontroller. Debugging can be configured with the define |
'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging |
calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is |
2, DBG1 and DBG2 logs will be printed. |
A debug log consists of a label ('prefix') to indicate which debug log created |
the output and a memory block to dump in hex ('data' and 'len'). |
*/ |
#ifndef F_CPU |
# define F_CPU 12000000 /* 12 MHz */ |
#endif |
/* make sure we have the UART defines: */ |
#include "iarcompat.h" |
#ifndef __IAR_SYSTEMS_ICC__ |
# include <avr/io.h> |
#endif |
#ifndef uchar |
# define uchar unsigned char |
#endif |
#if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */ |
# warning "Debugging disabled because device has no UART" |
# undef DEBUG_LEVEL |
#endif |
#ifndef DEBUG_LEVEL |
# define DEBUG_LEVEL 0 |
#endif |
/* ------------------------------------------------------------------------- */ |
#if DEBUG_LEVEL > 0 |
# define DBG1(prefix, data, len) odDebug(prefix, data, len) |
#else |
# define DBG1(prefix, data, len) |
#endif |
#if DEBUG_LEVEL > 1 |
# define DBG2(prefix, data, len) odDebug(prefix, data, len) |
#else |
# define DBG2(prefix, data, len) |
#endif |
/* ------------------------------------------------------------------------- */ |
#if DEBUG_LEVEL > 0 |
extern void odDebug(uchar prefix, uchar *data, uchar len); |
/* Try to find our control registers; ATMEL likes to rename these */ |
#if defined UBRR |
# define ODDBG_UBRR UBRR |
#elif defined UBRRL |
# define ODDBG_UBRR UBRRL |
#elif defined UBRR0 |
# define ODDBG_UBRR UBRR0 |
#elif defined UBRR0L |
# define ODDBG_UBRR UBRR0L |
#endif |
#if defined UCR |
# define ODDBG_UCR UCR |
#elif defined UCSRB |
# define ODDBG_UCR UCSRB |
#elif defined UCSR0B |
# define ODDBG_UCR UCSR0B |
#endif |
#if defined TXEN |
# define ODDBG_TXEN TXEN |
#else |
# define ODDBG_TXEN TXEN0 |
#endif |
#if defined USR |
# define ODDBG_USR USR |
#elif defined UCSRA |
# define ODDBG_USR UCSRA |
#elif defined UCSR0A |
# define ODDBG_USR UCSR0A |
#endif |
#if defined UDRE |
# define ODDBG_UDRE UDRE |
#else |
# define ODDBG_UDRE UDRE0 |
#endif |
#if defined UDR |
# define ODDBG_UDR UDR |
#elif defined UDR0 |
# define ODDBG_UDR UDR0 |
#endif |
static inline void odDebugInit(void) |
{ |
ODDBG_UCR |= (1<<ODDBG_TXEN); |
ODDBG_UBRR = F_CPU / (19200 * 16L) - 1; |
} |
#else |
# define odDebugInit() |
#endif |
/* ------------------------------------------------------------------------- */ |
#endif /* __oddebug_h_included__ */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/usbconfig-prototype.h |
---|
0,0 → 1,246 |
/* Name: usbconfig.h |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2005-04-01 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: usbconfig-prototype.h 275 2007-03-20 09:58:28Z cs $ |
*/ |
#ifndef __usbconfig_h_included__ |
#define __usbconfig_h_included__ |
/* |
General Description: |
This file is an example configuration (with inline documentation) for the USB |
driver. It configures AVR-USB for an ATMega8 with USB D+ connected to Port D |
bit 2 (which is also hardware interrupt 0) and USB D- to Port D bit 0. You may |
wire the lines to any other port, as long as D+ is also wired to INT0. |
To create your own usbconfig.h file, copy this file to the directory |
containing "usbdrv" (that is your project firmware source directory) and |
rename it to "usbconfig.h". Then edit it accordingly. |
*/ |
/* ---------------------------- Hardware Config ---------------------------- */ |
#define USB_CFG_IOPORTNAME D |
/* This is the port where the USB bus is connected. When you configure it to |
* "B", the registers PORTB, PINB and DDRB will be used. |
*/ |
#define USB_CFG_DMINUS_BIT 0 |
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. |
* This may be any bit in the port. |
*/ |
#define USB_CFG_DPLUS_BIT 2 |
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. |
* This may be any bit in the port. Please note that D+ must also be connected |
* to interrupt pin INT0! |
*/ |
/* ----------------------- Optional Hardware Config ------------------------ */ |
/* #define USB_CFG_PULLUP_IOPORTNAME D */ |
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of |
* V+, you can connect and disconnect the device from firmware by calling |
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). |
* This constant defines the port on which the pullup resistor is connected. |
*/ |
/* #define USB_CFG_PULLUP_BIT 4 */ |
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined |
* above) where the 1.5k pullup resistor is connected. See description |
* above for details. |
*/ |
/* --------------------------- Functional Range ---------------------------- */ |
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1 |
/* Define this to 1 if you want to compile a version with two endpoints: The |
* default control endpoint 0 and an interrupt-in endpoint 1. |
*/ |
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 |
/* Define this to 1 if you want to compile a version with three endpoints: The |
* default control endpoint 0, an interrupt-in endpoint 1 and an interrupt-in |
* endpoint 3. You must also enable endpoint 1 above. |
*/ |
#define USB_CFG_IMPLEMENT_HALT 0 |
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature |
* for endpoint 1 (interrupt endpoint). Although you may not need this feature, |
* it is required by the standard. We have made it a config option because it |
* bloats the code considerably. |
*/ |
#define USB_CFG_INTR_POLL_INTERVAL 20 |
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll |
* interval. The value is in milliseconds and must not be less than 10 ms for |
* low speed devices. |
*/ |
#define USB_CFG_IS_SELF_POWERED 0 |
/* Define this to 1 if the device has its own power supply. Set it to 0 if the |
* device is powered from the USB bus. |
*/ |
#define USB_CFG_MAX_BUS_POWER 100 |
/* Set this variable to the maximum USB bus power consumption of your device. |
* The value is in milliamperes. [It will be divided by two since USB |
* communicates power requirements in units of 2 mA.] |
*/ |
#define USB_CFG_IMPLEMENT_FN_WRITE 0 |
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out |
* transfers. Set it to 0 if you don't need it and want to save a couple of |
* bytes. |
*/ |
#define USB_CFG_IMPLEMENT_FN_READ 0 |
/* Set this to 1 if you need to send control replies which are generated |
* "on the fly" when usbFunctionRead() is called. If you only want to send |
* data from a static buffer, set it to 0 and return the data from |
* usbFunctionSetup(). This saves a couple of bytes. |
*/ |
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 |
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoint 1. |
* You must implement the function usbFunctionWriteOut() which receives all |
* interrupt/bulk data sent to endpoint 1. |
*/ |
#define USB_CFG_HAVE_FLOWCONTROL 0 |
/* Define this to 1 if you want flowcontrol over USB data. See the definition |
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in |
* usbdrv.h. |
*/ |
/* -------------------------- Device Description --------------------------- */ |
#define USB_CFG_VENDOR_ID 0xc0, 0x16 |
/* USB vendor ID for the device, low byte first. If you have registered your |
* own Vendor ID, define it here. Otherwise you use obdev's free shared |
* VID/PID pair. Be sure to read USBID-License.txt for rules! |
* This template uses obdev's shared VID/PID pair for HIDs: 0x16c0/0x5df. |
* Use this VID/PID pair ONLY if you understand the implications! |
*/ |
#define USB_CFG_DEVICE_ID 0xdf, 0x05 |
/* This is the ID of the product, low byte first. It is interpreted in the |
* scope of the vendor ID. If you have registered your own VID with usb.org |
* or if you have licensed a PID from somebody else, define it here. Otherwise |
* you use obdev's free shared VID/PID pair. Be sure to read the rules in |
* USBID-License.txt! |
* This template uses obdev's shared VID/PID pair for HIDs: 0x16c0/0x5df. |
* Use this VID/PID pair ONLY if you understand the implications! |
*/ |
#define USB_CFG_DEVICE_VERSION 0x00, 0x01 |
/* Version number of the device: Minor number first, then major number. |
*/ |
#define USB_CFG_VENDOR_NAME 'w', 'w', 'w', '.', 'o', 'b', 'd', 'e', 'v', '.', 'a', 't' |
#define USB_CFG_VENDOR_NAME_LEN 12 |
/* These two values define the vendor name returned by the USB device. The name |
* must be given as a list of characters under single quotes. The characters |
* are interpreted as Unicode (UTF-16) entities. |
* If you don't want a vendor name string, undefine these macros. |
* ALWAYS define a vendor name containing your Internet domain name if you use |
* obdev's free shared VID/PID pair. See the file USBID-License.txt for |
* details. |
*/ |
#define USB_CFG_DEVICE_NAME 'T', 'e', 'm', 'p', 'l', 'a', 't', 'e' |
#define USB_CFG_DEVICE_NAME_LEN 8 |
/* Same as above for the device name. If you don't want a device name, undefine |
* the macros. See the file USBID-License.txt before you assign a name if you |
* use a shared VID/PID. |
*/ |
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ |
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ |
/* Same as above for the serial number. If you don't want a serial number, |
* undefine the macros. |
* It may be useful to provide the serial number through other means than at |
* compile time. See the section about descriptor properties below for how |
* to fine tune control over USB descriptors such as the string descriptor |
* for the serial number. |
*/ |
#define USB_CFG_DEVICE_CLASS 0 |
#define USB_CFG_DEVICE_SUBCLASS 0 |
/* See USB specification if you want to conform to an existing device class. |
*/ |
#define USB_CFG_INTERFACE_CLASS 3 /* HID */ |
#define USB_CFG_INTERFACE_SUBCLASS 0 |
#define USB_CFG_INTERFACE_PROTOCOL 0 |
/* See USB specification if you want to conform to an existing device class or |
* protocol. |
* This template defines a HID class device. If you implement a vendor class |
* device, set USB_CFG_INTERFACE_CLASS to 0 and USB_CFG_DEVICE_CLASS to 0xff. |
*/ |
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 42 /* total length of report descriptor */ |
/* Define this to the length of the HID report descriptor, if you implement |
* an HID device. Otherwise don't define it or define it to 0. |
* Since this template defines a HID device, it must also specify a HID |
* report descriptor length. You must add a PROGMEM character array named |
* "usbHidReportDescriptor" to your code which contains the report descriptor. |
* Don't forget to keep the array and this define in sync! |
*/ |
/* ------------------- Fine Control over USB Descriptors ------------------- */ |
/* If you don't want to use the driver's default USB descriptors, you can |
* provide our own. These can be provided as (1) fixed length static data in |
* flash memory, (2) fixed length static data in RAM or (3) dynamically at |
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more |
* information about this function. |
* Descriptor handling is configured through the descriptor's properties. If |
* no properties are defined or if they are 0, the default descriptor is used. |
* Possible properties are: |
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched |
* at runtime via usbFunctionDescriptor(). |
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found |
* in static memory is in RAM, not in flash memory. |
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), |
* the driver must know the descriptor's length. The descriptor itself is |
* found at the address of a well known identifier (see below). |
* List of static descriptor names (must be declared PROGMEM if in flash): |
* char usbDescriptorDevice[]; |
* char usbDescriptorConfiguration[]; |
* char usbDescriptorHidReport[]; |
* char usbDescriptorString0[]; |
* int usbDescriptorStringVendor[]; |
* int usbDescriptorStringDevice[]; |
* int usbDescriptorStringSerialNumber[]; |
* Other descriptors can't be provided statically, they must be provided |
* dynamically at runtime. |
* |
* Descriptor properties are or-ed or added together, e.g.: |
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) |
* |
* The following descriptors are defined: |
* USB_CFG_DESCR_PROPS_DEVICE |
* USB_CFG_DESCR_PROPS_CONFIGURATION |
* USB_CFG_DESCR_PROPS_STRINGS |
* USB_CFG_DESCR_PROPS_STRING_0 |
* USB_CFG_DESCR_PROPS_STRING_VENDOR |
* USB_CFG_DESCR_PROPS_STRING_PRODUCT |
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER |
* USB_CFG_DESCR_PROPS_HID |
* USB_CFG_DESCR_PROPS_HID_REPORT |
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) |
* |
*/ |
#define USB_CFG_DESCR_PROPS_DEVICE 0 |
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 |
#define USB_CFG_DESCR_PROPS_STRINGS 0 |
#define USB_CFG_DESCR_PROPS_STRING_0 0 |
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 |
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 |
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 |
#define USB_CFG_DESCR_PROPS_HID 0 |
#define USB_CFG_DESCR_PROPS_HID_REPORT 0 |
#define USB_CFG_DESCR_PROPS_UNKNOWN 0 |
/* ----------------------- Optional MCU Description ------------------------ */ |
/* The following configurations have working defaults in usbdrv.h. You |
* usually don't need to set them explicitly. Only if you want to run |
* the driver on a device which is not yet supported or with a compiler |
* which is not fully supported (such as IAR C) or if you use a differnt |
* interrupt than INT0, you may have to define some of these. |
*/ |
/* #define USB_INTR_CFG MCUCR */ |
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ |
/* #define USB_INTR_CFG_CLR 0 */ |
/* #define USB_INTR_ENABLE GIMSK */ |
/* #define USB_INTR_ENABLE_BIT INT0 */ |
/* #define USB_INTR_PENDING GIFR */ |
/* #define USB_INTR_PENDING_BIT INTF0 */ |
#endif /* __usbconfig_h_included__ */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/usbdrv.c |
---|
0,0 → 1,551 |
/* Name: usbdrv.c |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2004-12-29 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: usbdrv.c,v 1.3 2007/06/07 13:53:47 harbaum Exp $ |
*/ |
#include "iarcompat.h" |
#ifndef __IAR_SYSTEMS_ICC__ |
# include <avr/io.h> |
# include <avr/pgmspace.h> |
#endif |
#include "usbdrv.h" |
#include "oddebug.h" |
/* |
General Description: |
This module implements the C-part of the USB driver. See usbdrv.h for a |
documentation of the entire driver. |
*/ |
#ifndef IAR_SECTION |
#define IAR_SECTION(arg) |
#define __no_init |
#endif |
/* The macro IAR_SECTION is a hack to allow IAR-cc compatibility. On gcc, it |
* is defined to nothing. __no_init is required on IAR. |
*/ |
/* ------------------------------------------------------------------------- */ |
/* raw USB registers / interface to assembler code: */ |
uchar usbRxBuf[2*USB_BUFSIZE]; /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */ |
uchar usbInputBufOffset; /* offset in usbRxBuf used for low level receiving */ |
uchar usbDeviceAddr; /* assigned during enumeration, defaults to 0 */ |
uchar usbNewDeviceAddr; /* device ID which should be set after status phase */ |
uchar usbConfiguration; /* currently selected configuration. Administered by driver, but not used */ |
volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */ |
uchar usbCurrentTok; /* last token received, if more than 1 rx endpoint: MSb=endpoint */ |
uchar usbRxToken; /* token for data we received; if more than 1 rx endpoint: MSb=endpoint */ |
uchar usbMsgLen = 0xff; /* remaining number of bytes, no msg to send if -1 (see usbMsgPtr) */ |
volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */ |
uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */ |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
volatile uchar usbTxLen1 = USBPID_NAK; /* TX count for endpoint 1 */ |
uchar usbTxBuf1[USB_BUFSIZE]; /* TX data for endpoint 1 */ |
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
volatile uchar usbTxLen3 = USBPID_NAK; /* TX count for endpoint 1 */ |
uchar usbTxBuf3[USB_BUFSIZE]; /* TX data for endpoint 1 */ |
#endif |
#endif |
/* USB status registers / not shared with asm code */ |
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */ |
static uchar usbMsgFlags; /* flag values see below */ |
#define USB_FLG_TX_PACKET (1<<0) |
/* Leave free 6 bits after TX_PACKET. This way we can increment usbMsgFlags to toggle TX_PACKET */ |
#define USB_FLG_MSGPTR_IS_ROM (1<<6) |
#define USB_FLG_USE_DEFAULT_RW (1<<7) |
/* |
optimizing hints: |
- do not post/pre inc/dec integer values in operations |
- assign value of PRG_RDB() to register variables and don't use side effects in arg |
- use narrow scope for variables which should be in X/Y/Z register |
- assign char sized expressions to variables to force 8 bit arithmetics |
*/ |
/* ------------------------------------------------------------------------- */ |
#if USB_CFG_DESCR_PROPS_STRINGS == 0 |
#if USB_CFG_DESCR_PROPS_STRING_0 == 0 |
#undef USB_CFG_DESCR_PROPS_STRING_0 |
#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0) |
PROGMEM char usbDescriptorString0[] = { /* language descriptor */ |
4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */ |
3, /* descriptor type */ |
0x09, 0x04, /* language index (0x0409 = US-English) */ |
}; |
#endif |
#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN |
#undef USB_CFG_DESCR_PROPS_STRING_VENDOR |
#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor) |
PROGMEM int usbDescriptorStringVendor[] = { |
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN), |
USB_CFG_VENDOR_NAME |
}; |
#endif |
#if USB_CFG_DESCR_PROPS_STRING_DEVICE == 0 && USB_CFG_DEVICE_NAME_LEN |
#undef USB_CFG_DESCR_PROPS_STRING_DEVICE |
#define USB_CFG_DESCR_PROPS_STRING_DEVICE sizeof(usbDescriptorStringDevice) |
PROGMEM int usbDescriptorStringDevice[] = { |
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN), |
USB_CFG_DEVICE_NAME |
}; |
#endif |
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN |
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER |
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber) |
PROGMEM int usbDescriptorStringSerialNumber[] = { |
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN), |
USB_CFG_SERIAL_NUMBER |
}; |
#endif |
#endif /* USB_CFG_DESCR_PROPS_STRINGS == 0 */ |
#if USB_CFG_DESCR_PROPS_DEVICE == 0 |
#undef USB_CFG_DESCR_PROPS_DEVICE |
#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice) |
PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */ |
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */ |
USBDESCR_DEVICE, /* descriptor type */ |
0x10, 0x01, /* USB version supported */ |
USB_CFG_DEVICE_CLASS, |
USB_CFG_DEVICE_SUBCLASS, |
0, /* protocol */ |
8, /* max packet size */ |
USB_CFG_VENDOR_ID, /* 2 bytes */ |
USB_CFG_DEVICE_ID, /* 2 bytes */ |
USB_CFG_DEVICE_VERSION, /* 2 bytes */ |
USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0, /* manufacturer string index */ |
USB_CFG_DESCR_PROPS_STRING_DEVICE != 0 ? 2 : 0, /* product string index */ |
USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, /* serial number string index */ |
1, /* number of configurations */ |
}; |
#endif |
#if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0 |
#undef USB_CFG_DESCR_PROPS_HID |
#define USB_CFG_DESCR_PROPS_HID 9 /* length of HID descriptor in config descriptor below */ |
#endif |
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0 |
#undef USB_CFG_DESCR_PROPS_CONFIGURATION |
#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration) |
PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ |
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ |
USBDESCR_CONFIG, /* descriptor type */ |
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + (USB_CFG_DESCR_PROPS_HID & 0xff), 0, |
/* total length of data returned (including inlined descriptors) */ |
1, /* number of interfaces in this configuration */ |
1, /* index of this configuration */ |
0, /* configuration name string index */ |
#if USB_CFG_IS_SELF_POWERED |
USBATTR_SELFPOWER, /* attributes */ |
#else |
USBATTR_BUSPOWER, /* attributes */ |
#endif |
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */ |
/* interface descriptor follows inline: */ |
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */ |
USBDESCR_INTERFACE, /* descriptor type */ |
0, /* index of this interface */ |
0, /* alternate setting for this interface */ |
USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */ |
USB_CFG_INTERFACE_CLASS, |
USB_CFG_INTERFACE_SUBCLASS, |
USB_CFG_INTERFACE_PROTOCOL, |
0, /* string index for interface */ |
#if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */ |
9, /* sizeof(usbDescrHID): length of descriptor in bytes */ |
USBDESCR_HID, /* descriptor type: HID */ |
0x01, 0x01, /* BCD representation of HID version */ |
0x00, /* target country code */ |
0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ |
0x22, /* descriptor type: report */ |
USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */ |
#endif |
#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */ |
7, /* sizeof(usbDescrEndpoint) */ |
USBDESCR_ENDPOINT, /* descriptor type = endpoint */ |
0x81, /* IN endpoint number 1 */ |
0x03, /* attrib: Interrupt endpoint */ |
8, 0, /* maximum packet size */ |
USB_CFG_INTR_POLL_INTERVAL, /* in ms */ |
#endif |
}; |
#endif |
/* We don't use prog_int or prog_int16_t for compatibility with various libc |
* versions. Here's an other compatibility hack: |
*/ |
#ifndef PRG_RDB |
#define PRG_RDB(addr) pgm_read_byte(addr) |
#endif |
typedef union{ |
unsigned word; |
uchar *ptr; |
uchar bytes[2]; |
}converter_t; |
/* We use this union to do type conversions. This is better optimized than |
* type casts in gcc 3.4.3 and much better than using bit shifts to build |
* ints from chars. Byte ordering is not a problem on an 8 bit platform. |
*/ |
/* ------------------------------------------------------------------------- */ |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
void usbSetInterrupt(uchar *data, uchar len) |
{ |
uchar *p, i; |
#if USB_CFG_IMPLEMENT_HALT |
if(usbTxLen1 == USBPID_STALL) |
return; |
#endif |
#if 0 /* No runtime checks! Caller is responsible for valid data! */ |
if(len > 8) /* interrupt transfers are limited to 8 bytes */ |
len = 8; |
#endif |
if(usbTxLen1 & 0x10){ /* packet buffer was empty */ |
usbTxBuf1[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */ |
}else{ |
usbTxLen1 = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */ |
} |
p = usbTxBuf1 + 1; |
for(i=len;i--;) |
*p++ = *data++; |
usbCrc16Append(&usbTxBuf1[1], len); |
usbTxLen1 = len + 4; /* len must be given including sync byte */ |
DBG2(0x21, usbTxBuf1, len + 3); |
} |
#endif |
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
void usbSetInterrupt3(uchar *data, uchar len) |
{ |
uchar *p, i; |
if(usbTxLen3 & 0x10){ /* packet buffer was empty */ |
usbTxBuf3[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */ |
}else{ |
usbTxLen3 = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */ |
} |
p = usbTxBuf3 + 1; |
for(i=len;i--;) |
*p++ = *data++; |
usbCrc16Append(&usbTxBuf3[1], len); |
usbTxLen3 = len + 4; /* len must be given including sync byte */ |
DBG2(0x23, usbTxBuf3, len + 3); |
} |
#endif |
static uchar usbRead(uchar *data, uchar len) |
{ |
#if USB_CFG_IMPLEMENT_FN_READ |
if(usbMsgFlags & USB_FLG_USE_DEFAULT_RW){ |
#endif |
uchar i = len, *r = usbMsgPtr; |
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ |
while(i--){ |
uchar c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */ |
*data++ = c; |
r++; |
} |
}else{ /* RAM data */ |
while(i--) |
*data++ = *r++; |
} |
usbMsgPtr = r; |
return len; |
#if USB_CFG_IMPLEMENT_FN_READ |
}else{ |
if(len != 0) /* don't bother app with 0 sized reads */ |
return usbFunctionRead(data, len); |
return 0; |
} |
#endif |
} |
#define GET_DESCRIPTOR(cfgProp, staticName) \ |
if(cfgProp){ \ |
if((cfgProp) & USB_PROP_IS_RAM) \ |
flags &= ~USB_FLG_MSGPTR_IS_ROM; \ |
if((cfgProp) & USB_PROP_IS_DYNAMIC){ \ |
replyLen = usbFunctionDescriptor(rq); \ |
}else{ \ |
replyData = (uchar *)(staticName); \ |
SET_REPLY_LEN((cfgProp) & 0xff); \ |
} \ |
} |
/* We use if() instead of #if in the macro above because #if can't be used |
* in macros and the compiler optimizes constant conditions anyway. |
*/ |
/* Don't make this function static to avoid inlining. |
* The entire function would become too large and exceed the range of |
* relative jumps. |
* 2006-02-25: Either gcc 3.4.3 is better than the gcc used when the comment |
* above was written, or other parts of the code have changed. We now get |
* better results with an inlined function. Test condition: PowerSwitch code. |
*/ |
static void usbProcessRx(uchar *data, uchar len) |
{ |
usbRequest_t *rq = (void *)data; |
uchar replyLen = 0, flags = USB_FLG_USE_DEFAULT_RW; |
/* We use if() cascades because the compare is done byte-wise while switch() |
* is int-based. The if() cascades are therefore more efficient. |
*/ |
/* usbRxToken can be: |
* 0x2d 00101101 (USBPID_SETUP for endpoint 0) |
* 0xe1 11100001 (USBPID_OUT for endpoint 0) |
* 0xff 11111111 (USBPID_OUT for endpoint 1) |
*/ |
DBG2(0x10 + ((usbRxToken >> 1) & 3), data, len); /* SETUP0=12; OUT0=10; OUT1=13 */ |
#if USB_CFG_IMPLEMENT_FN_WRITEOUT |
if(usbRxToken == 0xff){ |
usbFunctionWriteOut(data, len); |
return; /* no reply expected, hence no usbMsgPtr, usbMsgFlags, usbMsgLen set */ |
} |
#endif |
if(usbRxToken == (uchar)USBPID_SETUP){ |
usbTxLen = USBPID_NAK; /* abort pending transmit */ |
if(len == 8){ /* Setup size must be always 8 bytes. Ignore otherwise. */ |
uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; |
if(type == USBRQ_TYPE_STANDARD){ |
#define SET_REPLY_LEN(len) replyLen = (len); usbMsgPtr = replyData |
/* This macro ensures that replyLen and usbMsgPtr are always set in the same way. |
* That allows optimization of common code in if() branches */ |
uchar *replyData = usbTxBuf + 9; /* there is 3 bytes free space at the end of the buffer */ |
replyData[0] = 0; /* common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ |
if(rq->bRequest == USBRQ_GET_STATUS){ /* 0 */ |
uchar __attribute__((__unused__)) recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */ |
#if USB_CFG_IS_SELF_POWERED |
if(recipient == USBRQ_RCPT_DEVICE) |
replyData[0] = USB_CFG_IS_SELF_POWERED; |
#endif |
#if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_IMPLEMENT_HALT |
if(recipient == USBRQ_RCPT_ENDPOINT && rq->wIndex.bytes[0] == 0x81) /* request status for endpoint 1 */ |
replyData[0] = usbTxLen1 == USBPID_STALL; |
#endif |
replyData[1] = 0; |
SET_REPLY_LEN(2); |
}else if(rq->bRequest == USBRQ_SET_ADDRESS){ /* 5 */ |
usbNewDeviceAddr = rq->wValue.bytes[0]; |
}else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */ |
flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW; |
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ /* 1 */ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice) |
}else if(rq->wValue.bytes[1] == USBDESCR_CONFIG){ /* 2 */ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) |
}else if(rq->wValue.bytes[1] == USBDESCR_STRING){ /* 3 */ |
#if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC |
if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) |
flags &= ~USB_FLG_MSGPTR_IS_ROM; |
replyLen = usbFunctionDescriptor(rq); |
#else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ |
if(rq->wValue.bytes[0] == 0){ /* descriptor index */ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0) |
}else if(rq->wValue.bytes[0] == 1){ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor) |
}else if(rq->wValue.bytes[0] == 2){ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_DEVICE, usbDescriptorStringDevice) |
}else if(rq->wValue.bytes[0] == 3){ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber) |
}else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ |
replyLen = usbFunctionDescriptor(rq); |
} |
#endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ |
}else if(rq->wValue.bytes[1] == USBDESCR_HID){ /* 0x21 */ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18) |
}else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){ /* 0x22 */ |
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport) |
}else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ |
replyLen = usbFunctionDescriptor(rq); |
} |
}else if(rq->bRequest == USBRQ_GET_CONFIGURATION){ /* 8 */ |
replyData = &usbConfiguration; /* send current configuration value */ |
SET_REPLY_LEN(1); |
}else if(rq->bRequest == USBRQ_SET_CONFIGURATION){ /* 9 */ |
usbConfiguration = rq->wValue.bytes[0]; |
#if USB_CFG_IMPLEMENT_HALT |
usbTxLen1 = USBPID_NAK; |
#endif |
}else if(rq->bRequest == USBRQ_GET_INTERFACE){ /* 10 */ |
SET_REPLY_LEN(1); |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
}else if(rq->bRequest == USBRQ_SET_INTERFACE){ /* 11 */ |
USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# endif |
# if USB_CFG_IMPLEMENT_HALT |
usbTxLen1 = USBPID_NAK; |
}else if(rq->bRequest == USBRQ_CLEAR_FEATURE || rq->bRequest == USBRQ_SET_FEATURE){ /* 1|3 */ |
if(rq->wValue.bytes[0] == 0 && rq->wIndex.bytes[0] == 0x81){ /* feature 0 == HALT for endpoint == 1 */ |
usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL; |
USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# endif |
} |
# endif |
#endif |
}else{ |
/* the following requests can be ignored, send default reply */ |
/* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */ |
/* 12: SYNCH_FRAME */ |
} |
#undef SET_REPLY_LEN |
}else{ /* not a standard request -- must be vendor or class request */ |
replyLen = usbFunctionSetup(data); |
} |
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE |
if(replyLen == 0xff){ /* use user-supplied read/write function */ |
if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST){ |
replyLen = rq->wLength.bytes[0]; /* IN transfers only */ |
} |
flags &= ~USB_FLG_USE_DEFAULT_RW; /* we have no valid msg, use user supplied read/write functions */ |
}else /* The 'else' prevents that we limit a replyLen of 0xff to the maximum transfer len. */ |
#endif |
if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */ |
replyLen = rq->wLength.bytes[0]; |
} |
/* make sure that data packets which are sent as ACK to an OUT transfer are always zero sized */ |
}else{ /* DATA packet from out request */ |
#if USB_CFG_IMPLEMENT_FN_WRITE |
if(!(usbMsgFlags & USB_FLG_USE_DEFAULT_RW)){ |
uchar rval = usbFunctionWrite(data, len); |
replyLen = 0xff; |
if(rval == 0xff){ /* an error occurred */ |
usbMsgLen = 0xff; /* cancel potentially pending data packet for ACK */ |
usbTxLen = USBPID_STALL; |
}else if(rval != 0){ /* This was the final package */ |
replyLen = 0; /* answer with a zero-sized data packet */ |
} |
flags = 0; /* start with a DATA1 package, stay with user supplied write() function */ |
} |
#endif |
} |
usbMsgFlags = flags; |
usbMsgLen = replyLen; |
} |
/* ------------------------------------------------------------------------- */ |
static void usbBuildTxBlock(void) |
{ |
uchar wantLen, len, txLen, token; |
wantLen = usbMsgLen; |
if(wantLen > 8) |
wantLen = 8; |
usbMsgLen -= wantLen; |
token = USBPID_DATA1; |
if(usbMsgFlags & USB_FLG_TX_PACKET) |
token = USBPID_DATA0; |
usbMsgFlags++; |
len = usbRead(usbTxBuf + 1, wantLen); |
if(len <= 8){ /* valid data packet */ |
usbCrc16Append(&usbTxBuf[1], len); |
txLen = len + 4; /* length including sync byte */ |
if(len < 8) /* a partial package identifies end of message */ |
usbMsgLen = 0xff; |
}else{ |
txLen = USBPID_STALL; /* stall the endpoint */ |
usbMsgLen = 0xff; |
} |
usbTxBuf[0] = token; |
usbTxLen = txLen; |
DBG2(0x20, usbTxBuf, txLen-1); |
} |
static inline uchar isNotSE0(void) |
{ |
uchar rval; |
/* We want to do |
* return (USBIN & USBMASK); |
* here, but the compiler does int-expansion acrobatics. |
* We can avoid this by assigning to a char-sized variable. |
*/ |
rval = USBIN & USBMASK; |
return rval; |
} |
/* ------------------------------------------------------------------------- */ |
void usbPoll(void) |
{ |
uchar len, i; |
if((len = usbRxLen) > 0){ |
/* We could check CRC16 here -- but ACK has already been sent anyway. If you |
* need data integrity checks with this driver, check the CRC in your app |
* code and report errors back to the host. Since the ACK was already sent, |
* retries must be handled on application level. |
* unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); |
*/ |
usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len - 3); |
#if USB_CFG_HAVE_FLOWCONTROL |
if(usbRxLen > 0) /* only mark as available if not inactivated */ |
usbRxLen = 0; |
#else |
usbRxLen = 0; /* mark rx buffer as available */ |
#endif |
} |
if(usbTxLen & 0x10){ /* transmit system idle */ |
if(usbMsgLen != 0xff){ /* transmit data pending? */ |
usbBuildTxBlock(); |
} |
} |
for(i = 10; i > 0; i--){ |
if(isNotSE0()) |
break; |
} |
if(i == 0){ /* RESET condition, called multiple times during reset */ |
usbNewDeviceAddr = 0; |
usbDeviceAddr = 0; |
#if USB_CFG_IMPLEMENT_HALT |
usbTxLen1 = USBPID_NAK; |
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
usbTxLen3 = USBPID_NAK; |
#endif |
#endif |
DBG1(0xff, 0, 0); |
} |
} |
/* ------------------------------------------------------------------------- */ |
void usbInit(void) |
{ |
#if USB_INTR_CFG_SET != 0 |
USB_INTR_CFG |= USB_INTR_CFG_SET; |
#endif |
#if USB_INTR_CFG_CLR != 0 |
USB_INTR_CFG &= ~(USB_INTR_CFG_CLR); |
#endif |
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
USB_SET_DATATOKEN1(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
USB_SET_DATATOKEN3(USBPID_DATA0); /* reset data toggling for interrupt endpoint */ |
# endif |
#endif |
} |
/* ------------------------------------------------------------------------- */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/usbdrv.h |
---|
0,0 → 1,633 |
/* Name: usbdrv.h |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2004-12-29 |
* Tabsize: 4 |
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: usbdrv.h,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
#ifndef __usbdrv_h_included__ |
#define __usbdrv_h_included__ |
#include "usbconfig.h" |
#include "iarcompat.h" |
/* |
Hardware Prerequisites: |
======================= |
USB lines D+ and D- MUST be wired to the same I/O port. D+ must (also) be |
connected to INT0. D- requires a pullup of 1.5k to +3.5V (and the device |
must be powered at 3.5V) to identify as low-speed USB device. A pullup of |
1M SHOULD be connected from D+ to +3.5V to prevent interference when no USB |
master is connected. We use D+ as interrupt source and not D- because it |
does not trigger on keep-alive and RESET states. |
As a compile time option, the 1.5k pullup resistor on D- can be made |
switchable to allow the device to disconnect at will. See the definition of |
usbDeviceConnect() and usbDeviceDisconnect() further down in this file. |
Please adapt the values in usbconfig.h according to your hardware! |
The device MUST be clocked at 12 MHz. This is more than the 10 MHz allowed by |
an AT90S2313 powered at 4.5V. However, if the supply voltage to maximum clock |
relation is interpolated linearly, an ATtiny2313 meets the requirement by |
specification. In practice, the AT90S2313 can be overclocked and works well. |
Limitations: |
============ |
Robustness with respect to communication errors: |
The driver assumes error-free communication. It DOES check for errors in |
the PID, but does NOT check bit stuffing errors, SE0 in middle of a byte, |
token CRC (5 bit) and data CRC (16 bit). CRC checks can not be performed due |
to timing constraints: We must start sending a reply within 7 bit times. |
Bit stuffing and misplaced SE0 would have to be checked in real-time, but CPU |
performance does not permit that. The driver does not check Data0/Data1 |
toggling, but application software can implement the check. |
Input characteristics: |
Since no differential receiver circuit is used, electrical interference |
robustness may suffer. The driver samples only one of the data lines with |
an ordinary I/O pin's input characteristics. However, since this is only a |
low speed USB implementation and the specification allows for 8 times the |
bit rate over the same hardware, we should be on the safe side. Even the spec |
requires detection of asymmetric states at high bit rate for SE0 detection. |
Number of endpoints: |
The driver supports up to four endpoints: One control endpoint (endpoint 0), |
two interrupt-in (or bulk-in) endpoints (endpoint 1 and 3) and one |
interrupt-out (or bulk-out) endpoint (endpoint 1). Please note that the USB |
standard forbids bulk endpoints for low speed devices! Most operating systems |
allow them anyway, but the AVR will spend 90% of the CPU time in the USB |
interrupt polling for bulk data. |
By default, only the control endpoint 0 is enabled. To get the other endpoints, |
define USB_CFG_HAVE_INTRIN_ENDPOINT, USB_CFG_HAVE_INTRIN_ENDPOINT3 and/or |
USB_CFG_IMPLEMENT_FN_WRITEOUT respectively (see usbconfig-prototype.h for |
details). |
Maximum data payload: |
Data payload of control in and out transfers may be up to 254 bytes. In order |
to accept payload data of out transfers, you need to implement |
'usbFunctionWrite()'. |
USB Suspend Mode supply current: |
The USB standard limits power consumption to 500uA when the bus is in suspend |
mode. This is not a problem for self-powered devices since they don't need |
bus power anyway. Bus-powered devices can achieve this only by putting the |
CPU in sleep mode. The driver does not implement suspend handling by itself. |
However, the application may implement activity monitoring and wakeup from |
sleep. The host sends regular SE0 states on the bus to keep it active. These |
SE0 states can be detected by wiring the INT1 pin to D-. It is not necessary |
to enable the interrupt, checking the interrupt pending flag should suffice. |
Before entering sleep mode, the application should enable INT1 for a wakeup |
on the next bus activity. |
Operation without an USB master: |
The driver behaves neutral without connection to an USB master if D- reads |
as 1. To avoid spurious interrupts, we recommend a high impedance (e.g. 1M) |
pullup resistor on D+. If D- becomes statically 0, the driver may block in |
the interrupt routine. |
Interrupt latency: |
The application must ensure that the USB interrupt is not disabled for more |
than 20 cycles. This implies that all interrupt routines must either be |
declared as "INTERRUPT" instead of "SIGNAL" (see "avr/signal.h") or that they |
are written in assembler with "sei" as the first instruction. |
Maximum interrupt duration / CPU cycle consumption: |
The driver handles all USB communication during the interrupt service |
routine. The routine will not return before an entire USB message is received |
and the reply is sent. This may be up to ca. 1200 cycles = 100us if the host |
conforms to the standard. The driver will consume CPU cycles for all USB |
messages, even if they address another (low-speed) device on the same bus. |
*/ |
/* ------------------------------------------------------------------------- */ |
/* --------------------------- Module Interface ---------------------------- */ |
/* ------------------------------------------------------------------------- */ |
#define USBDRV_VERSION 20070319 |
/* This define uniquely identifies a driver version. It is a decimal number |
* constructed from the driver's release date in the form YYYYMMDD. If the |
* driver's behavior or interface changes, you can use this constant to |
* distinguish versions. If it is not defined, the driver's release date is |
* older than 2006-01-25. |
*/ |
#ifndef __ASSEMBLER__ |
#ifndef uchar |
#define uchar unsigned char |
#endif |
#ifndef schar |
#define schar signed char |
#endif |
/* shortcuts for well defined 8 bit integer types */ |
struct usbRequest; /* forward declaration */ |
extern void usbInit(void); |
/* This function must be called before interrupts are enabled and the main |
* loop is entered. |
*/ |
extern void usbPoll(void); |
/* This function must be called at regular intervals from the main loop. |
* Maximum delay between calls is somewhat less than 50ms (USB timeout for |
* accepting a Setup message). Otherwise the device will not be recognized. |
* Please note that debug outputs through the UART take ~ 0.5ms per byte |
* at 19200 bps. |
*/ |
extern uchar *usbMsgPtr; |
/* This variable may be used to pass transmit data to the driver from the |
* implementation of usbFunctionWrite(). It is also used internally by the |
* driver for standard control requests. |
*/ |
extern uchar usbFunctionSetup(uchar data[8]); |
/* This function is called when the driver receives a SETUP transaction from |
* the host which is not answered by the driver itself (in practice: class and |
* vendor requests). All control transfers start with a SETUP transaction where |
* the host communicates the parameters of the following (optional) data |
* transfer. The SETUP data is available in the 'data' parameter which can |
* (and should) be casted to 'usbRequest_t *' for a more user-friendly access |
* to parameters. |
* |
* If the SETUP indicates a control-in transfer, you should provide the |
* requested data to the driver. There are two ways to transfer this data: |
* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data |
* block and return the length of the data in 'usbFunctionSetup()'. The driver |
* will handle the rest. Or (2) return 0xff in 'usbFunctionSetup()'. The driver |
* will then call 'usbFunctionRead()' when data is needed. See the |
* documentation for usbFunctionRead() for details. |
* |
* If the SETUP indicates a control-out transfer, the only way to receive the |
* data from the host is through the 'usbFunctionWrite()' call. If you |
* implement this function, you must return 0xff in 'usbFunctionSetup()' to |
* indicate that 'usbFunctionWrite()' should be used. See the documentation of |
* this function for more information. If you just want to ignore the data sent |
* by the host, return 0 in 'usbFunctionSetup()'. |
* |
* Note that calls to the functions usbFunctionRead() and usbFunctionWrite() |
* are only done if enabled by the configuration in usbconfig.h. |
*/ |
extern uchar usbFunctionDescriptor(struct usbRequest *rq); |
/* You need to implement this function ONLY if you provide USB descriptors at |
* runtime (which is an expert feature). It is very similar to |
* usbFunctionSetup() above, but it is called only to request USB descriptor |
* data. See the documentation of usbFunctionSetup() above for more info. |
*/ |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
void usbSetInterrupt(uchar *data, uchar len); |
/* This function sets the message which will be sent during the next interrupt |
* IN transfer. The message is copied to an internal buffer and must not exceed |
* a length of 8 bytes. The message may be 0 bytes long just to indicate the |
* interrupt status to the host. |
* If you need to transfer more bytes, use a control read after the interrupt. |
*/ |
extern volatile uchar usbTxLen1; |
#define usbInterruptIsReady() (usbTxLen1 & 0x10) |
/* This macro indicates whether the last interrupt message has already been |
* sent. If you set a new interrupt message before the old was sent, the |
* message already buffered will be lost. |
*/ |
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
void usbSetInterrupt3(uchar *data, uchar len); |
extern volatile uchar usbTxLen3; |
#define usbInterruptIsReady3() (usbTxLen3 & 0x10) |
/* Same as above for endpoint 3 */ |
#endif |
#endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */ |
#if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* simplified interface for backward compatibility */ |
#define usbHidReportDescriptor usbDescriptorHidReport |
/* should be declared as: PROGMEM char usbHidReportDescriptor[]; */ |
/* If you implement an HID device, you need to provide a report descriptor. |
* The HID report descriptor syntax is a bit complex. If you understand how |
* report descriptors are constructed, we recommend that you use the HID |
* Descriptor Tool from usb.org, see http://www.usb.org/developers/hidpage/. |
* Otherwise you should probably start with a working example. |
*/ |
#endif /* USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH */ |
#if USB_CFG_IMPLEMENT_FN_WRITE |
extern uchar usbFunctionWrite(uchar *data, uchar len); |
/* This function is called by the driver to provide a control transfer's |
* payload data (control-out). It is called in chunks of up to 8 bytes. The |
* total count provided in the current control transfer can be obtained from |
* the 'length' property in the setup data. If an error occurred during |
* processing, return 0xff (== -1). The driver will answer the entire transfer |
* with a STALL token in this case. If you have received the entire payload |
* successfully, return 1. If you expect more data, return 0. If you don't |
* know whether the host will send more data (you should know, the total is |
* provided in the usbFunctionSetup() call!), return 1. |
* NOTE: If you return 0xff for STALL, 'usbFunctionWrite()' may still be called |
* for the remaining data. You must continue to return 0xff for STALL in these |
* calls. |
* In order to get usbFunctionWrite() called, define USB_CFG_IMPLEMENT_FN_WRITE |
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. |
*/ |
#endif /* USB_CFG_IMPLEMENT_FN_WRITE */ |
#if USB_CFG_IMPLEMENT_FN_READ |
extern uchar usbFunctionRead(uchar *data, uchar len); |
/* This function is called by the driver to ask the application for a control |
* transfer's payload data (control-in). It is called in chunks of up to 8 |
* bytes each. You should copy the data to the location given by 'data' and |
* return the actual number of bytes copied. If you return less than requested, |
* the control-in transfer is terminated. If you return 0xff, the driver aborts |
* the transfer with a STALL token. |
* In order to get usbFunctionRead() called, define USB_CFG_IMPLEMENT_FN_READ |
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. |
*/ |
#endif /* USB_CFG_IMPLEMENT_FN_READ */ |
#if USB_CFG_IMPLEMENT_FN_WRITEOUT |
extern void usbFunctionWriteOut(uchar *data, uchar len); |
/* This function is called by the driver when data on interrupt-out or bulk- |
* out endpoint 1 is received. You must define USB_CFG_IMPLEMENT_FN_WRITEOUT |
* to 1 in usbconfig.h to get this function called. |
*/ |
#endif /* USB_CFG_IMPLEMENT_FN_WRITEOUT */ |
#ifdef USB_CFG_PULLUP_IOPORTNAME |
#define usbDeviceConnect() ((USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT)), \ |
(USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT))) |
/* This macro (intended to look like a function) connects the device to the |
* USB bus. It is only available if you have defined the constants |
* USB_CFG_PULLUP_IOPORT and USB_CFG_PULLUP_BIT in usbconfig.h. |
*/ |
#define usbDeviceDisconnect() ((USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT)), \ |
(USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT))) |
/* This macro (intended to look like a function) disconnects the device from |
* the USB bus. It is only available if you have defined the constants |
* USB_CFG_PULLUP_IOPORT and USB_CFG_PULLUP_BIT in usbconfig.h. |
*/ |
#endif /* USB_CFG_PULLUP_IOPORT */ |
extern unsigned usbCrc16(unsigned data, uchar len); |
#define usbCrc16(data, len) usbCrc16((unsigned)(data), len) |
/* This function calculates the binary complement of the data CRC used in |
* USB data packets. The value is used to build raw transmit packets. |
* You may want to use this function for data checksums or to verify received |
* data. We enforce 16 bit calling conventions for compatibility with IAR's |
* tiny memory model. |
*/ |
extern unsigned usbCrc16Append(unsigned data, uchar len); |
#define usbCrc16Append(data, len) usbCrc16Append((unsigned)(data), len) |
/* This function is equivalent to usbCrc16() above, except that it appends |
* the 2 bytes CRC (lowbyte first) in the 'data' buffer after reading 'len' |
* bytes. |
*/ |
extern uchar usbConfiguration; |
/* This value contains the current configuration set by the host. The driver |
* allows setting and querying of this variable with the USB SET_CONFIGURATION |
* and GET_CONFIGURATION requests, but does not use it otherwise. |
* You may want to reflect the "configured" status with a LED on the device or |
* switch on high power parts of the circuit only if the device is configured. |
*/ |
#define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8)) |
/* This macro builds a descriptor header for a string descriptor given the |
* string's length. See usbdrv.c for an example how to use it. |
*/ |
#if USB_CFG_HAVE_FLOWCONTROL |
extern volatile schar usbRxLen; |
#define usbDisableAllRequests() usbRxLen = -1 |
/* Must be called from usbFunctionWrite(). This macro disables all data input |
* from the USB interface. Requests from the host are answered with a NAK |
* while they are disabled. |
*/ |
#define usbEnableAllRequests() usbRxLen = 0 |
/* May only be called if requests are disabled. This macro enables input from |
* the USB interface after it has been disabled with usbDisableAllRequests(). |
*/ |
#define usbAllRequestsAreDisabled() (usbRxLen < 0) |
/* Use this macro to find out whether requests are disabled. It may be needed |
* to ensure that usbEnableAllRequests() is never called when requests are |
* enabled. |
*/ |
#endif |
#define USB_SET_DATATOKEN1(token) usbTxBuf1[0] = token |
#define USB_SET_DATATOKEN3(token) usbTxBuf3[0] = token |
/* These two macros can be used by application software to reset data toggling |
* for interrupt-in endpoints 1 and 3. |
*/ |
#endif /* __ASSEMBLER__ */ |
/* ------------------------------------------------------------------------- */ |
/* ----------------- Definitions for Descriptor Properties ----------------- */ |
/* ------------------------------------------------------------------------- */ |
/* This is advanced stuff. See usbconfig-prototype.h for more information |
* about the various methods to define USB descriptors. If you do nothing, |
* the default descriptors will be used. |
*/ |
#define USB_PROP_IS_DYNAMIC (1 << 8) |
/* If this property is set for a descriptor, usbFunctionDescriptor() will be |
* used to obtain the particular descriptor. |
*/ |
#define USB_PROP_IS_RAM (1 << 9) |
/* If this property is set for a descriptor, the data is read from RAM |
* memory instead of Flash. The property is used for all methods to provide |
* external descriptors. |
*/ |
#define USB_PROP_LENGTH(len) ((len) & 0xff) |
/* If a static external descriptor is used, this is the total length of the |
* descriptor in bytes. |
*/ |
/* all descriptors which may have properties: */ |
#ifndef USB_CFG_DESCR_PROPS_DEVICE |
#define USB_CFG_DESCR_PROPS_DEVICE 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_CONFIGURATION |
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_STRINGS |
#define USB_CFG_DESCR_PROPS_STRINGS 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_STRING_0 |
#define USB_CFG_DESCR_PROPS_STRING_0 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_STRING_VENDOR |
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_STRING_DEVICE |
#define USB_CFG_DESCR_PROPS_STRING_DEVICE 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER |
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 |
#endif |
#ifndef USB_CFG_DESCR_PROPS_HID |
#define USB_CFG_DESCR_PROPS_HID 0 |
#endif |
#if !(USB_CFG_DESCR_PROPS_HID_REPORT) |
# undef USB_CFG_DESCR_PROPS_HID_REPORT |
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* do some backward compatibility tricks */ |
# define USB_CFG_DESCR_PROPS_HID_REPORT USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH |
# else |
# define USB_CFG_DESCR_PROPS_HID_REPORT 0 |
# endif |
#endif |
#ifndef USB_CFG_DESCR_PROPS_UNKNOWN |
#define USB_CFG_DESCR_PROPS_UNKNOWN 0 |
#endif |
/* ------------------ forward declaration of descriptors ------------------- */ |
/* If you use external static descriptors, they must be stored in global |
* arrays as declared below: |
*/ |
#ifndef __ASSEMBLER__ |
extern |
#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
char usbDescriptorDevice[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
char usbDescriptorConfiguration[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
char usbDescriptorHidReport[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
char usbDescriptorString0[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
int usbDescriptorStringVendor[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
int usbDescriptorStringDevice[]; |
extern |
#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM) |
PROGMEM |
#endif |
int usbDescriptorStringSerialNumber[]; |
#endif /* __ASSEMBLER__ */ |
/* ------------------------------------------------------------------------- */ |
/* ------------------------ General Purpose Macros ------------------------- */ |
/* ------------------------------------------------------------------------- */ |
#define USB_CONCAT(a, b) a ## b |
#define USB_CONCAT_EXPANDED(a, b) USB_CONCAT(a, b) |
#define USB_OUTPORT(name) USB_CONCAT(PORT, name) |
#define USB_INPORT(name) USB_CONCAT(PIN, name) |
#define USB_DDRPORT(name) USB_CONCAT(DDR, name) |
/* The double-define trick above lets us concatenate strings which are |
* defined by macros. |
*/ |
/* ------------------------------------------------------------------------- */ |
/* ------------------------- Constant definitions -------------------------- */ |
/* ------------------------------------------------------------------------- */ |
#if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID) |
#warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h" |
/* If the user has not defined IDs, we default to obdev's free IDs. |
* See USBID-License.txt for details. |
*/ |
#endif |
/* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */ |
#ifndef USB_CFG_VENDOR_ID |
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* 5824 in dec, stands for VOTI */ |
#endif |
#ifndef USB_CFG_DEVICE_ID |
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH |
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* 1503 in dec, shared PID for HIDs */ |
# elif USB_CFG_INTERFACE_CLASS == 2 |
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* 1505 in dec, shared PID for CDC Modems */ |
# else |
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* 1500 in dec, obdev's free PID */ |
# endif |
#endif |
/* Derive Output, Input and DataDirection ports from port names */ |
#ifndef USB_CFG_IOPORTNAME |
#error "You must define USB_CFG_IOPORTNAME in usbconfig.h, see usbconfig-prototype.h" |
#endif |
#define USBOUT USB_OUTPORT(USB_CFG_IOPORTNAME) |
#define USB_PULLUP_OUT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME) |
#define USBIN USB_INPORT(USB_CFG_IOPORTNAME) |
#define USBDDR USB_DDRPORT(USB_CFG_IOPORTNAME) |
#define USB_PULLUP_DDR USB_DDRPORT(USB_CFG_PULLUP_IOPORTNAME) |
#define USBMINUS USB_CFG_DMINUS_BIT |
#define USBPLUS USB_CFG_DPLUS_BIT |
#define USBIDLE (1<<USB_CFG_DMINUS_BIT) /* value representing J state */ |
#define USBMASK ((1<<USB_CFG_DPLUS_BIT) | (1<<USB_CFG_DMINUS_BIT)) /* mask for USB I/O bits */ |
/* defines for backward compatibility with older driver versions: */ |
#define USB_CFG_IOPORT USB_OUTPORT(USB_CFG_IOPORTNAME) |
#ifdef USB_CFG_PULLUP_IOPORTNAME |
#define USB_CFG_PULLUP_IOPORT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME) |
#endif |
#define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */ |
/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */ |
#ifndef USB_INTR_CFG /* allow user to override our default */ |
# if defined EICRA |
# define USB_INTR_CFG EICRA |
# else |
# define USB_INTR_CFG MCUCR |
# endif |
#endif |
#ifndef USB_INTR_CFG_SET /* allow user to override our default */ |
# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */ |
#endif |
#ifndef USB_INTR_CFG_CLR /* allow user to override our default */ |
# define USB_INTR_CFG_CLR 0 /* no bits to clear */ |
#endif |
#ifndef USB_INTR_ENABLE /* allow user to override our default */ |
# if defined GIMSK |
# define USB_INTR_ENABLE GIMSK |
# elif defined EIMSK |
# define USB_INTR_ENABLE EIMSK |
# else |
# define USB_INTR_ENABLE GICR |
# endif |
#endif |
#ifndef USB_INTR_ENABLE_BIT /* allow user to override our default */ |
# define USB_INTR_ENABLE_BIT INT0 |
#endif |
#ifndef USB_INTR_PENDING /* allow user to override our default */ |
# if defined EIFR |
# define USB_INTR_PENDING EIFR |
# else |
# define USB_INTR_PENDING GIFR |
# endif |
#endif |
#ifndef USB_INTR_PENDING_BIT /* allow user to override our default */ |
# define USB_INTR_PENDING_BIT INTF0 |
#endif |
/* |
The defines above don't work for the following chips |
at90c8534: no ISC0?, no PORTB, can't find a data sheet |
at86rf401: no PORTB, no MCUCR etc, low clock rate |
atmega103: no ISC0? (maybe omission in header, can't find data sheet) |
atmega603: not defined in avr-libc |
at43usb320, at43usb355, at76c711: have USB anyway |
at94k: is different... |
at90s1200, attiny11, attiny12, attiny15, attiny28: these have no RAM |
*/ |
/* ------------------------------------------------------------------------- */ |
/* ----------------- USB Specification Constants and Types ----------------- */ |
/* ------------------------------------------------------------------------- */ |
/* USB Token values */ |
#define USBPID_SETUP 0x2d |
#define USBPID_OUT 0xe1 |
#define USBPID_IN 0x69 |
#define USBPID_DATA0 0xc3 |
#define USBPID_DATA1 0x4b |
#define USBPID_ACK 0xd2 |
#define USBPID_NAK 0x5a |
#define USBPID_STALL 0x1e |
#ifndef __ASSEMBLER__ |
extern uchar usbTxBuf1[USB_BUFSIZE], usbTxBuf3[USB_BUFSIZE]; |
typedef union usbWord{ |
unsigned word; |
uchar bytes[2]; |
}usbWord_t; |
typedef struct usbRequest{ |
uchar bmRequestType; |
uchar bRequest; |
usbWord_t wValue; |
usbWord_t wIndex; |
usbWord_t wLength; |
}usbRequest_t; |
/* This structure matches the 8 byte setup request */ |
#endif |
/* bmRequestType field in USB setup: |
* d t t r r r r r, where |
* d ..... direction: 0=host->device, 1=device->host |
* t ..... type: 0=standard, 1=class, 2=vendor, 3=reserved |
* r ..... recipient: 0=device, 1=interface, 2=endpoint, 3=other |
*/ |
/* USB setup recipient values */ |
#define USBRQ_RCPT_MASK 0x1f |
#define USBRQ_RCPT_DEVICE 0 |
#define USBRQ_RCPT_INTERFACE 1 |
#define USBRQ_RCPT_ENDPOINT 2 |
/* USB request type values */ |
#define USBRQ_TYPE_MASK 0x60 |
#define USBRQ_TYPE_STANDARD (0<<5) |
#define USBRQ_TYPE_CLASS (1<<5) |
#define USBRQ_TYPE_VENDOR (2<<5) |
/* USB direction values: */ |
#define USBRQ_DIR_MASK 0x80 |
#define USBRQ_DIR_HOST_TO_DEVICE (0<<7) |
#define USBRQ_DIR_DEVICE_TO_HOST (1<<7) |
/* USB Standard Requests */ |
#define USBRQ_GET_STATUS 0 |
#define USBRQ_CLEAR_FEATURE 1 |
#define USBRQ_SET_FEATURE 3 |
#define USBRQ_SET_ADDRESS 5 |
#define USBRQ_GET_DESCRIPTOR 6 |
#define USBRQ_SET_DESCRIPTOR 7 |
#define USBRQ_GET_CONFIGURATION 8 |
#define USBRQ_SET_CONFIGURATION 9 |
#define USBRQ_GET_INTERFACE 10 |
#define USBRQ_SET_INTERFACE 11 |
#define USBRQ_SYNCH_FRAME 12 |
/* USB descriptor constants */ |
#define USBDESCR_DEVICE 1 |
#define USBDESCR_CONFIG 2 |
#define USBDESCR_STRING 3 |
#define USBDESCR_INTERFACE 4 |
#define USBDESCR_ENDPOINT 5 |
#define USBDESCR_HID 0x21 |
#define USBDESCR_HID_REPORT 0x22 |
#define USBDESCR_HID_PHYS 0x23 |
#define USBATTR_BUSPOWER 0x80 |
#define USBATTR_SELFPOWER 0x40 |
#define USBATTR_REMOTEWAKE 0x20 |
/* USB HID Requests */ |
#define USBRQ_HID_GET_REPORT 0x01 |
#define USBRQ_HID_GET_IDLE 0x02 |
#define USBRQ_HID_GET_PROTOCOL 0x03 |
#define USBRQ_HID_SET_REPORT 0x09 |
#define USBRQ_HID_SET_IDLE 0x0a |
#define USBRQ_HID_SET_PROTOCOL 0x0b |
/* ------------------------------------------------------------------------- */ |
#endif /* __usbdrv_h_included__ */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/usbdrvasm.S |
---|
0,0 → 1,710 |
/* Name: usbdrvasm.S |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2004-12-29 |
* Tabsize: 4 |
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: usbdrvasm.S,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
/* |
General Description: |
This module implements the assembler part of the USB driver. See usbdrv.h |
for a description of the entire driver. |
Since almost all of this code is timing critical, don't change unless you |
really know what you are doing! Many parts require not only a maximum number |
of CPU cycles, but even an exact number of cycles! |
Timing constraints according to spec (in bit times): |
timing subject min max CPUcycles |
--------------------------------------------------------------------------- |
EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2 16 16-128 |
EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60 |
DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60 |
*/ |
#include "iarcompat.h" |
#ifndef __IAR_SYSTEMS_ASM__ |
/* configs for io.h */ |
# define __SFR_OFFSET 0 |
# define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ |
# include <avr/io.h> /* for CPU I/O register definitions and vectors */ |
#endif /* __IAR_SYSTEMS_ASM__ */ |
#include "usbdrv.h" /* for common defs */ |
/* register names */ |
#define x1 r16 |
#define x2 r17 |
#define shift r18 |
#define cnt r19 |
#define x3 r20 |
#define x4 r21 |
/* Some assembler dependent definitions and declarations: */ |
#ifdef __IAR_SYSTEMS_ASM__ |
# define nop2 rjmp $+2 /* jump to next instruction */ |
# define XL r26 |
# define XH r27 |
# define YL r28 |
# define YH r29 |
# define ZL r30 |
# define ZH r31 |
# define lo8(x) LOW(x) |
# define hi8(x) ((x)>>8) /* not HIGH to allow XLINK to make a proper range check */ |
extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset |
extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen |
extern usbTxBuf, usbMsgLen, usbTxLen1, usbTxBuf1, usbTxLen3, usbTxBuf3 |
public usbCrc16 |
public usbCrc16Append |
COMMON INTVEC |
ORG INT0_vect |
rjmp SIG_INTERRUPT0 |
RSEG CODE |
#else /* __IAR_SYSTEMS_ASM__ */ |
# define nop2 rjmp .+0 /* jump to next instruction */ |
.text |
.global SIG_INTERRUPT0 |
.type SIG_INTERRUPT0, @function |
.global usbCrc16 |
.global usbCrc16Append |
#endif /* __IAR_SYSTEMS_ASM__ */ |
;Software-receiver engine. Strict timing! Don't change unless you can preserve timing! |
;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled |
;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable |
;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes |
;Numbers in brackets are maximum cycles since SOF. |
SIG_INTERRUPT0: |
;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt |
push YL ;2 [35] push only what is necessary to sync with edge ASAP |
in YL, SREG ;1 [37] |
push YL ;2 [39] |
;---------------------------------------------------------------------------- |
; Synchronize with sync pattern: |
;---------------------------------------------------------------------------- |
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] |
;sync up with J to K edge during sync pattern -- use fastest possible loops |
;first part has no timeout because it waits for IDLE or SE1 (== disconnected) |
waitForJ: |
sbis USBIN, USBMINUS ;1 [40] wait for D- == 1 |
rjmp waitForJ ;2 |
waitForK: |
;The following code results in a sampling window of 1/4 bit which meets the spec. |
sbis USBIN, USBMINUS |
rjmp foundK |
sbis USBIN, USBMINUS |
rjmp foundK |
sbis USBIN, USBMINUS |
rjmp foundK |
sbis USBIN, USBMINUS |
rjmp foundK |
sbis USBIN, USBMINUS |
rjmp foundK |
rjmp sofError |
foundK: |
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] |
;we have 1 bit time for setup purposes, then sample again. Numbers in brackets |
;are cycles from center of first sync (double K) bit after the instruction |
push YH ;2 [2] |
lds YL, usbInputBufOffset;2 [4] |
clr YH ;1 [5] |
subi YL, lo8(-(usbRxBuf));1 [6] |
sbci YH, hi8(-(usbRxBuf));1 [7] |
sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] |
rjmp haveTwoBitsK ;2 [10] |
pop YH ; undo the push from before |
rjmp waitForK ; this was not the end of sync, retry |
haveTwoBitsK: |
;---------------------------------------------------------------------------- |
; push more registers and initialize values while we sample the first bits: |
;---------------------------------------------------------------------------- |
push shift ;2 [16] |
push x1 ;2 [12] |
push x2 ;2 [14] |
in x1, USBIN ;1 [17] <-- sample bit 0 |
ldi shift, 0xff ;1 [18] |
bst x1, USBMINUS ;1 [19] |
bld shift, 0 ;1 [20] |
push x3 ;2 [22] |
push cnt ;2 [24] |
in x2, USBIN ;1 [25] <-- sample bit 1 |
ser x3 ;1 [26] [inserted init instruction] |
eor x1, x2 ;1 [27] |
bst x1, USBMINUS ;1 [28] |
bld shift, 1 ;1 [29] |
ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] |
rjmp rxbit2 ;2 [32] |
;---------------------------------------------------------------------------- |
; Receiver loop (numbers in brackets are cycles within byte after instr) |
;---------------------------------------------------------------------------- |
unstuff0: ;1 (branch taken) |
andi x3, ~0x01 ;1 [15] |
mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit |
in x2, USBIN ;1 [17] <-- sample bit 1 again |
ori shift, 0x01 ;1 [18] |
rjmp didUnstuff0 ;2 [20] |
unstuff1: ;1 (branch taken) |
mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit |
andi x3, ~0x02 ;1 [22] |
ori shift, 0x02 ;1 [23] |
nop ;1 [24] |
in x1, USBIN ;1 [25] <-- sample bit 2 again |
rjmp didUnstuff1 ;2 [27] |
unstuff2: ;1 (branch taken) |
andi x3, ~0x04 ;1 [29] |
ori shift, 0x04 ;1 [30] |
mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit |
nop ;1 [32] |
in x2, USBIN ;1 [33] <-- sample bit 3 |
rjmp didUnstuff2 ;2 [35] |
unstuff3: ;1 (branch taken) |
in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] |
andi x3, ~0x08 ;1 [35] |
ori shift, 0x08 ;1 [36] |
rjmp didUnstuff3 ;2 [38] |
unstuff4: ;1 (branch taken) |
andi x3, ~0x10 ;1 [40] |
in x1, USBIN ;1 [41] <-- sample stuffed bit 4 |
ori shift, 0x10 ;1 [42] |
rjmp didUnstuff4 ;2 [44] |
unstuff5: ;1 (branch taken) |
andi x3, ~0x20 ;1 [48] |
in x2, USBIN ;1 [49] <-- sample stuffed bit 5 |
ori shift, 0x20 ;1 [50] |
rjmp didUnstuff5 ;2 [52] |
unstuff6: ;1 (branch taken) |
andi x3, ~0x40 ;1 [56] |
in x1, USBIN ;1 [57] <-- sample stuffed bit 6 |
ori shift, 0x40 ;1 [58] |
rjmp didUnstuff6 ;2 [60] |
; extra jobs done during bit interval: |
; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] |
; bit 1: se0 check |
; bit 2: overflow check |
; bit 3: recovery from delay [bit 0 tasks took too long] |
; bit 4: none |
; bit 5: none |
; bit 6: none |
; bit 7: jump, eor |
rxLoop: |
eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others |
in x1, USBIN ;1 [1] <-- sample bit 0 |
st y+, x3 ;2 [3] store data |
ser x3 ;1 [4] |
nop ;1 [5] |
eor x2, x1 ;1 [6] |
bst x2, USBMINUS;1 [7] |
bld shift, 0 ;1 [8] |
in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) |
andi x2, USBMASK ;1 [10] |
breq se0 ;1 [11] SE0 check for bit 1 |
andi shift, 0xf9 ;1 [12] |
didUnstuff0: |
breq unstuff0 ;1 [13] |
eor x1, x2 ;1 [14] |
bst x1, USBMINUS;1 [15] |
bld shift, 1 ;1 [16] |
rxbit2: |
in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) |
andi shift, 0xf3 ;1 [18] |
breq unstuff1 ;1 [19] do remaining work for bit 1 |
didUnstuff1: |
subi cnt, 1 ;1 [20] |
brcs overflow ;1 [21] loop control |
eor x2, x1 ;1 [22] |
bst x2, USBMINUS;1 [23] |
bld shift, 2 ;1 [24] |
in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) |
andi shift, 0xe7 ;1 [26] |
breq unstuff2 ;1 [27] |
didUnstuff2: |
eor x1, x2 ;1 [28] |
bst x1, USBMINUS;1 [29] |
bld shift, 3 ;1 [30] |
didUnstuff3: |
andi shift, 0xcf ;1 [31] |
breq unstuff3 ;1 [32] |
in x1, USBIN ;1 [33] <-- sample bit 4 |
eor x2, x1 ;1 [34] |
bst x2, USBMINUS;1 [35] |
bld shift, 4 ;1 [36] |
didUnstuff4: |
andi shift, 0x9f ;1 [37] |
breq unstuff4 ;1 [38] |
nop2 ;2 [40] |
in x2, USBIN ;1 [41] <-- sample bit 5 |
eor x1, x2 ;1 [42] |
bst x1, USBMINUS;1 [43] |
bld shift, 5 ;1 [44] |
didUnstuff5: |
andi shift, 0x3f ;1 [45] |
breq unstuff5 ;1 [46] |
nop2 ;2 [48] |
in x1, USBIN ;1 [49] <-- sample bit 6 |
eor x2, x1 ;1 [50] |
bst x2, USBMINUS;1 [51] |
bld shift, 6 ;1 [52] |
didUnstuff6: |
cpi shift, 0x02 ;1 [53] |
brlo unstuff6 ;1 [54] |
nop2 ;2 [56] |
in x2, USBIN ;1 [57] <-- sample bit 7 |
eor x1, x2 ;1 [58] |
bst x1, USBMINUS;1 [59] |
bld shift, 7 ;1 [60] |
didUnstuff7: |
cpi shift, 0x04 ;1 [61] |
brsh rxLoop ;2 [63] loop control |
unstuff7: |
andi x3, ~0x80 ;1 [63] |
ori shift, 0x80 ;1 [64] |
in x2, USBIN ;1 [65] <-- sample stuffed bit 7 |
nop ;1 [66] |
rjmp didUnstuff7 ;2 [68] |
;---------------------------------------------------------------------------- |
; Processing of received packet (numbers in brackets are cycles after end of SE0) |
;---------------------------------------------------------------------------- |
;This is the only non-error exit point for the software receiver loop |
;we don't check any CRCs here because there is no time left. |
#define token x1 |
se0: ; [0] |
subi cnt, USB_BUFSIZE ;1 [1] |
neg cnt ;1 [2] |
cpi cnt, 3 ;1 [3] |
ldi x2, 1<<USB_INTR_PENDING_BIT ;1 [4] |
out USB_INTR_PENDING, x2;1 [5] clear pending intr and check flag later. SE0 should be over. |
brlo doReturn ;1 [6] this is probably an ACK, NAK or similar packet |
sub YL, cnt ;1 [7] |
sbci YH, 0 ;1 [8] |
ld token, y ;2 [10] |
cpi token, USBPID_DATA0 ;1 [11] |
breq handleData ;1 [12] |
cpi token, USBPID_DATA1 ;1 [13] |
breq handleData ;1 [14] |
ldd x2, y+1 ;2 [16] ADDR and 1 bit endpoint number |
mov x3, x2 ;1 [17] store for endpoint number |
andi x2, 0x7f ;1 [18] x2 is now ADDR |
lds shift, usbDeviceAddr;2 [20] |
cp x2, shift ;1 [21] |
overflow: ; This is a hack: brcs overflow will never have Z flag set |
brne ignorePacket ;1 [22] packet for different address |
cpi token, USBPID_IN ;1 [23] |
breq handleIn ;1 [24] |
cpi token, USBPID_SETUP ;1 [25] |
breq handleSetupOrOut ;1 [26] |
cpi token, USBPID_OUT ;1 [27] |
breq handleSetupOrOut ;1 [28] |
; rjmp ignorePacket ;fallthrough, should not happen anyway. |
ignorePacket: |
clr shift |
sts usbCurrentTok, shift |
doReturn: |
pop cnt |
pop x3 |
pop x2 |
pop x1 |
pop shift |
pop YH |
sofError: |
pop YL |
out SREG, YL |
pop YL |
reti |
#if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3 |
handleIn3: ;1 [38] (branch taken) |
lds cnt, usbTxLen3 ;2 [40] |
sbrc cnt, 4 ;2 [42] |
rjmp sendCntAndReti ;0 43 + 17 = 60 until SOP |
sts usbTxLen3, x1 ;2 [44] x1 == USBPID_NAK from above |
ldi YL, lo8(usbTxBuf3) ;1 [45] |
ldi YH, hi8(usbTxBuf3) ;1 [46] |
rjmp usbSendAndReti ;2 [48] + 13 = 61 until SOP (violates the spec by 1 cycle) |
#endif |
;Setup and Out are followed by a data packet two bit times (16 cycles) after |
;the end of SE0. The sync code allows up to 40 cycles delay from the start of |
;the sync pattern until the first bit is sampled. That's a total of 56 cycles. |
handleSetupOrOut: ;1 [29] (branch taken) |
#if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for second OUT endpoint, set usbCurrentTok to -1 */ |
sbrc x3, 7 ;1 [30] skip if endpoint 0 |
ldi token, -1 ;1 [31] indicate that this is endpoint 1 OUT |
#endif |
sts usbCurrentTok, token;2 [33] |
pop cnt ;2 [35] |
pop x3 ;2 [37] |
pop x2 ;2 [39] |
pop x1 ;2 [41] |
pop shift ;2 [43] |
pop YH ;2 [45] |
in YL, USB_INTR_PENDING;1 [46] |
sbrc YL, USB_INTR_PENDING_BIT;1 [47] check whether data is already arriving |
rjmp waitForJ ;2 [49] save the pops and pushes -- a new interrupt is aready pending |
rjmp sofError ;2 not an error, but it does the pops and reti we want |
handleData: ;1 [15] (branch taken) |
lds token, usbCurrentTok;2 [17] |
tst token ;1 [18] |
breq doReturn ;1 [19] |
lds x2, usbRxLen ;2 [21] |
tst x2 ;1 [22] |
brne sendNakAndReti ;1 [23] |
; 2006-03-11: The following two lines fix a problem where the device was not |
; recognized if usbPoll() was called less frequently than once every 4 ms. |
cpi cnt, 4 ;1 [24] zero sized data packets are status phase only -- ignore and ack |
brmi sendAckAndReti ;1 [25] keep rx buffer clean -- we must not NAK next SETUP |
sts usbRxLen, cnt ;2 [27] store received data, swap buffers |
sts usbRxToken, token ;2 [29] |
lds x2, usbInputBufOffset;2 [31] swap buffers |
ldi cnt, USB_BUFSIZE ;1 [32] |
sub cnt, x2 ;1 [33] |
sts usbInputBufOffset, cnt;2 [35] buffers now swapped |
rjmp sendAckAndReti ;2 [37] + 19 = 56 until SOP |
handleIn: ;1 [25] (branch taken) |
;We don't send any data as long as the C code has not processed the current |
;input data and potentially updated the output data. That's more efficient |
;in terms of code size than clearing the tx buffers when a packet is received. |
lds x1, usbRxLen ;2 [27] |
cpi x1, 1 ;1 [28] negative values are flow control, 0 means "buffer free" |
brge sendNakAndReti ;1 [29] unprocessed input packet? |
ldi x1, USBPID_NAK ;1 [30] prepare value for usbTxLen |
#if USB_CFG_HAVE_INTRIN_ENDPOINT |
sbrc x3, 7 ;2 [33] x3 contains addr + endpoint |
rjmp handleIn1 ;0 |
#endif |
lds cnt, usbTxLen ;2 [34] |
sbrc cnt, 4 ;2 [36] all handshake tokens have bit 4 set |
rjmp sendCntAndReti ;0 37 + 17 = 54 until SOP |
sts usbTxLen, x1 ;2 [38] x1 == USBPID_NAK from above |
ldi YL, lo8(usbTxBuf) ;1 [39] |
ldi YH, hi8(usbTxBuf) ;1 [40] |
rjmp usbSendAndReti ;2 [42] + 14 = 56 until SOP |
; Comment about when to set usbTxLen to USBPID_NAK: |
; We should set it back when we receive the ACK from the host. This would |
; be simple to implement: One static variable which stores whether the last |
; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the |
; ACK. However, we set it back immediately when we send the package, |
; assuming that no error occurs and the host sends an ACK. We save one byte |
; RAM this way and avoid potential problems with endless retries. The rest of |
; the driver assumes error-free transfers anyway. |
#if USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */ |
handleIn1: ;1 [33] (branch taken) |
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 |
; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint |
ldd x2, y+2 ;2 [35] |
sbrc x2, 0 ;2 [37] |
rjmp handleIn3 ;0 |
#endif |
lds cnt, usbTxLen1 ;2 [39] |
sbrc cnt, 4 ;2 [41] all handshake tokens have bit 4 set |
rjmp sendCntAndReti ;0 42 + 17 = 59 until SOP |
sts usbTxLen1, x1 ;2 [43] x1 == USBPID_NAK from above |
ldi YL, lo8(usbTxBuf1) ;1 [44] |
ldi YH, hi8(usbTxBuf1) ;1 [45] |
rjmp usbSendAndReti ;2 [47] + 13 = 60 until SOP |
#endif |
;---------------------------------------------------------------------------- |
; Transmitting data |
;---------------------------------------------------------------------------- |
bitstuff0: ;1 (for branch taken) |
eor x1, x4 ;1 |
ldi x2, 0 ;1 |
out USBOUT, x1 ;1 <-- out |
rjmp didStuff0 ;2 branch back 2 cycles earlier |
bitstuff1: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2 |
bitstuff2: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2 |
bitstuff3: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff3 ;2 jump back earlier and ror 0 into x2 |
bitstuff4: ;1 (for branch taken) |
eor x1, x4 ;1 |
ldi x2, 0 ;1 |
out USBOUT, x1 ;1 <-- out |
rjmp didStuff4 ;2 jump back 2 cycles earlier |
sendNakAndReti: ;0 [-19] 19 cycles until SOP |
ldi x3, USBPID_NAK ;1 [-18] |
rjmp usbSendX3 ;2 [-16] |
sendAckAndReti: ;0 [-19] 19 cycles until SOP |
ldi x3, USBPID_ACK ;1 [-18] |
rjmp usbSendX3 ;2 [-16] |
sendCntAndReti: ;0 [-17] 17 cycles until SOP |
mov x3, cnt ;1 [-16] |
usbSendX3: ;0 [-16] |
ldi YL, 20 ;1 [-15] 'x3' is R20 |
ldi YH, 0 ;1 [-14] |
ldi cnt, 2 ;1 [-13] |
; rjmp usbSendAndReti fallthrough |
; USB spec says: |
; idle = J |
; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 |
; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 |
; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) |
;usbSend: |
;pointer to data in 'Y' |
;number of bytes in 'cnt' -- including sync byte |
;uses: x1...x4, shift, cnt, Y |
;Numbers in brackets are time since first bit of sync pattern is sent |
usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP |
in x2, USBDDR ;1 [-12] |
ori x2, USBMASK ;1 [-11] |
sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups) |
in x1, USBOUT ;1 [-8] port mirror for tx loop |
out USBDDR, x2 ;1 [-7] <- acquire bus |
; need not init x2 (bitstuff history) because sync starts with 0 |
push x4 ;2 [-5] |
ldi x4, USBMASK ;1 [-4] exor mask |
ldi shift, 0x80 ;1 [-3] sync byte is first byte sent |
txLoop: ; [62] |
sbrs shift, 0 ;1 [-2] [62] |
eor x1, x4 ;1 [-1] [63] |
out USBOUT, x1 ;1 [0] <-- out bit 0 |
ror shift ;1 [1] |
ror x2 ;1 [2] |
didStuff0: |
cpi x2, 0xfc ;1 [3] |
brsh bitstuff0 ;1 [4] |
sbrs shift, 0 ;1 [5] |
eor x1, x4 ;1 [6] |
ror shift ;1 [7] |
didStuff1: |
out USBOUT, x1 ;1 [8] <-- out bit 1 |
ror x2 ;1 [9] |
cpi x2, 0xfc ;1 [10] |
brsh bitstuff1 ;1 [11] |
sbrs shift, 0 ;1 [12] |
eor x1, x4 ;1 [13] |
ror shift ;1 [14] |
didStuff2: |
ror x2 ;1 [15] |
out USBOUT, x1 ;1 [16] <-- out bit 2 |
cpi x2, 0xfc ;1 [17] |
brsh bitstuff2 ;1 [18] |
sbrs shift, 0 ;1 [19] |
eor x1, x4 ;1 [20] |
ror shift ;1 [21] |
didStuff3: |
ror x2 ;1 [22] |
cpi x2, 0xfc ;1 [23] |
out USBOUT, x1 ;1 [24] <-- out bit 3 |
brsh bitstuff3 ;1 [25] |
nop2 ;2 [27] |
ld x3, y+ ;2 [29] |
sbrs shift, 0 ;1 [30] |
eor x1, x4 ;1 [31] |
out USBOUT, x1 ;1 [32] <-- out bit 4 |
ror shift ;1 [33] |
ror x2 ;1 [34] |
didStuff4: |
cpi x2, 0xfc ;1 [35] |
brsh bitstuff4 ;1 [36] |
sbrs shift, 0 ;1 [37] |
eor x1, x4 ;1 [38] |
ror shift ;1 [39] |
didStuff5: |
out USBOUT, x1 ;1 [40] <-- out bit 5 |
ror x2 ;1 [41] |
cpi x2, 0xfc ;1 [42] |
brsh bitstuff5 ;1 [43] |
sbrs shift, 0 ;1 [44] |
eor x1, x4 ;1 [45] |
ror shift ;1 [46] |
didStuff6: |
ror x2 ;1 [47] |
out USBOUT, x1 ;1 [48] <-- out bit 6 |
cpi x2, 0xfc ;1 [49] |
brsh bitstuff6 ;1 [50] |
sbrs shift, 0 ;1 [51] |
eor x1, x4 ;1 [52] |
ror shift ;1 [53] |
didStuff7: |
ror x2 ;1 [54] |
cpi x2, 0xfc ;1 [55] |
out USBOUT, x1 ;1 [56] <-- out bit 7 |
brsh bitstuff7 ;1 [57] |
mov shift, x3 ;1 [58] |
dec cnt ;1 [59] |
brne txLoop ;1/2 [60/61] |
;make SE0: |
cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles] |
pop x4 ;2 [63] |
;brackets are cycles from start of SE0 now |
out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle |
nop2 ;2 [2] |
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: |
;set address only after data packet was sent, not after handshake |
lds x2, usbNewDeviceAddr;2 [4] |
subi YL, 20 + 2 ;1 [5] |
sbci YH, 0 ;1 [6] |
breq skipAddrAssign ;2 [8] |
sts usbDeviceAddr, x2;0 if not skipped: SE0 is one cycle longer |
skipAddrAssign: |
;end of usbDeviceAddress transfer |
ldi x2, 1<<USB_INTR_PENDING_BIT;1 [9] int0 occurred during TX -- clear pending flag |
out USB_INTR_PENDING, x2;1 [10] |
ori x1, USBIDLE ;1 [11] |
in x2, USBDDR ;1 [12] |
cbr x2, USBMASK ;1 [13] set both pins to input |
mov x3, x1 ;1 [14] |
cbr x3, USBMASK ;1 [15] configure no pullup on both pins |
out USBOUT, x1 ;1 [16] <-- out J (idle) -- end of SE0 (EOP signal) |
out USBDDR, x2 ;1 [17] <-- release bus now |
out USBOUT, x3 ;1 [18] <-- ensure no pull-up resistors are active |
rjmp doReturn |
bitstuff5: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff5 ;2 same trick as above... |
bitstuff6: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff6 ;2 same trick as above... |
bitstuff7: ;1 (for branch taken) |
eor x1, x4 ;1 |
rjmp didStuff7 ;2 same trick as above... |
;---------------------------------------------------------------------------- |
; Utility functions |
;---------------------------------------------------------------------------- |
#ifdef __IAR_SYSTEMS_ASM__ |
/* Register assignments for usbCrc16 on IAR cc */ |
/* Calling conventions on IAR: |
* First parameter passed in r16/r17, second in r18/r19 and so on. |
* Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) |
* Result is passed in r16/r17 |
* In case of the "tiny" memory model, pointers are only 8 bit with no |
* padding. We therefore pass argument 1 as "16 bit unsigned". |
*/ |
RTMODEL "__rt_version", "3" |
/* The line above will generate an error if cc calling conventions change. |
* The value "3" above is valid for IAR 4.10B/W32 |
*/ |
# define argLen r18 /* argument 2 */ |
# define argPtrL r16 /* argument 1 */ |
# define argPtrH r17 /* argument 1 */ |
# define resCrcL r16 /* result */ |
# define resCrcH r17 /* result */ |
# define ptrL ZL |
# define ptrH ZH |
# define ptr Z |
# define byte r22 |
# define bitCnt r19 |
# define polyL r20 |
# define polyH r21 |
# define scratch r23 |
#else /* __IAR_SYSTEMS_ASM__ */ |
/* Register assignments for usbCrc16 on gcc */ |
/* Calling conventions on gcc: |
* First parameter passed in r24/r25, second in r22/23 and so on. |
* Callee must preserve r1-r17, r28/r29 |
* Result is passed in r24/r25 |
*/ |
# define argLen r22 /* argument 2 */ |
# define argPtrL r24 /* argument 1 */ |
# define argPtrH r25 /* argument 1 */ |
# define resCrcL r24 /* result */ |
# define resCrcH r25 /* result */ |
# define ptrL XL |
# define ptrH XH |
# define ptr x |
# define byte r18 |
# define bitCnt r19 |
# define polyL r20 |
# define polyH r21 |
# define scratch r23 |
#endif |
; extern unsigned usbCrc16(unsigned char *data, unsigned char len); |
; data: r24/25 |
; len: r22 |
; temp variables: |
; r18: data byte |
; r19: bit counter |
; r20/21: polynomial |
; r23: scratch |
; r24/25: crc-sum |
; r26/27=X: ptr |
usbCrc16: |
mov ptrL, argPtrL |
mov ptrH, argPtrH |
ldi resCrcL, 0xff |
ldi resCrcH, 0xff |
ldi polyL, lo8(0xa001) |
ldi polyH, hi8(0xa001) |
crcByteLoop: |
subi argLen, 1 |
brcs crcReady |
ld byte, ptr+ |
ldi bitCnt, 8 |
crcBitLoop: |
mov scratch, byte |
eor scratch, resCrcL |
lsr resCrcH |
ror resCrcL |
lsr byte |
sbrs scratch, 0 |
rjmp crcNoXor |
eor resCrcL, polyL |
eor resCrcH, polyH |
crcNoXor: |
dec bitCnt |
brne crcBitLoop |
rjmp crcByteLoop |
crcReady: |
com resCrcL |
com resCrcH |
ret |
; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len); |
usbCrc16Append: |
rcall usbCrc16 |
st ptr+, resCrcL |
st ptr+, resCrcH |
ret |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbdrv/usbdrvasm.asm |
---|
0,0 → 1,21 |
/* Name: usbdrvasm.asm |
* Project: AVR USB driver |
* Author: Christian Starkjohann |
* Creation Date: 2006-03-01 |
* Tabsize: 4 |
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH |
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) |
* This Revision: $Id: usbdrvasm.asm,v 1.2 2007/05/19 12:30:11 harbaum Exp $ |
*/ |
/* |
General Description: |
The IAR compiler/assembler system prefers assembler files with file extension |
".asm". We simply provide this file as an alias for usbdrvasm.S. |
Thanks to Oleg Semyonov for his help with the IAR tools port! |
*/ |
#include "usbdrvasm.S" |
end |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/common.mk |
---|
0,0 → 1,61 |
# ====================================================================== |
# Common Makefile for USBtiny applications |
# |
# Macros to be defined before including this file: |
# |
# USBTINY - the location of this directory |
# TARGET_ARCH - gcc -mmcu= option with AVR device type |
# OBJECTS - the objects in addition to the USBtiny objects |
# FLASH_CMD - command to upload main.hex to flash |
# STACK - maximum stack size (optional) |
# FLASH - flash size (optional) |
# SRAM - SRAM size (optional) |
# SCHEM - Postscript version of the schematic to be generated |
# |
# Copyright (C) 2006 Dick Streefland |
# |
# This is free software, licensed under the terms of the GNU General |
# Public License as published by the Free Software Foundation. |
# ====================================================================== |
CC = avr-gcc |
CFLAGS = -Os -g -Wall -I. -I$(USBTINY) |
ASFLAGS = -Os -g -Wall -I. |
LDFLAGS = -g |
MODULES = crc.o int.o usb.o $(OBJECTS) |
UTIL = $(USBTINY)/../util |
main.hex: |
all: main.hex $(SCHEM) |
clean: |
rm -f main.elf *.o tags *.sch~ gschem.log |
clobber: clean |
rm -f main.hex $(SCHEM) |
main.elf: $(MODULES) |
$(LINK.o) -o $@ $(MODULES) |
main.hex: main.elf $(UTIL)/check.py |
@python $(UTIL)/check.py main.elf $(STACK) $(FLASH) $(SRAM) |
avr-objcopy -j .text -j .data -O ihex main.elf main.hex |
disasm: main.elf |
avr-objdump -S main.elf |
flash: main.hex |
$(FLASH_CMD) |
crc.o: $(USBTINY)/crc.S $(USBTINY)/def.h usbtiny.h |
$(COMPILE.c) $(USBTINY)/crc.S |
int.o: $(USBTINY)/int.S $(USBTINY)/def.h usbtiny.h |
$(COMPILE.c) $(USBTINY)/int.S |
usb.o: $(USBTINY)/usb.c $(USBTINY)/def.h $(USBTINY)/usb.h usbtiny.h |
$(COMPILE.c) $(USBTINY)/usb.c |
main.o: $(USBTINY)/usb.h |
%.ps: %.sch $(UTIL)/sch2ps |
$(UTIL)/sch2ps $< |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/crc.S |
---|
0,0 → 1,123 |
; ====================================================================== |
; Calculate and append CRC |
; |
; The CRC is calculated 4 bits at a time, using a precomputed table of |
; 16 values. Each value is 16 bits, but only the 8 significant bits are |
; stored. The table should not cross a 256-byte page. The check.py script |
; will check for this. |
; |
; A bitwise algorithm would be a little smaller, but takes more time. |
; In fact, it takes too much time for the USB controller in my laptop. |
; The poll frequently is so high, that a lot of time is spent in the |
; interrupt handler, sending NAK packets, leaving little time for the |
; actual checksum calculation. An 8 bit algoritm would be even faster, |
; but requires a lookup table of 512 bytes. |
; |
; Copyright (C) 2006 Dick Streefland |
; |
; This is free software, licensed under the terms of the GNU General |
; Public License as published by the Free Software Foundation. |
; ====================================================================== |
#include "def.h" |
; ---------------------------------------------------------------------- |
; void crc(unsigned char *data, unsigned char len); |
; ---------------------------------------------------------------------- |
#define data r24 |
#define len r22 |
#define b r18 |
#define tmp r19 |
#define zl r20 |
#define crc_l r24 |
#define crc_h r25 |
.text |
.global crc |
.type crc, @function |
crc: |
; crc = 0xffff |
movw XL, r24 |
ldi crc_h, 0xff |
ldi crc_l, 0xff |
lsl len |
breq done |
ldi zl, lo8(crc4tab) |
ldi ZH, hi8(crc4tab) |
next_nibble: |
; b = (len & 1 ? b >> 4 : *data++) |
swap b |
sbrs len, 0 |
ld b, X+ |
; index = (crc ^ b) & 0x0f |
mov ZL, crc_l |
eor ZL, b |
andi ZL, 0x0f |
; crc >>= 4 |
swap crc_h |
swap crc_l |
andi crc_l, 0x0f |
mov tmp, crc_h |
andi tmp, 0xf0 |
or crc_l, tmp |
andi crc_h, 0x0f |
; crc ^= crc4tab[index] |
add ZL, zl |
lpm tmp, Z+ |
eor crc_h, tmp |
andi tmp, 1 |
eor crc_h, tmp |
eor crc_l, tmp |
; next nibble |
dec len |
brne next_nibble |
done: |
; crc ^= 0xffff |
com crc_l |
com crc_h |
; append crc to buffer |
st X+, crc_l |
st X+, crc_h |
ret |
; ---------------------------------------------------------------------- |
; CRC table. As bits 1..8 are always zero, omit them. |
; ---------------------------------------------------------------------- |
.section .progmem.crc,"a",@progbits |
;;; .align 4 ; avoid crossing a page boundary |
crc4tab: |
.byte 0x00+0x00 |
.byte 0xcc+0x01 |
.byte 0xd8+0x01 |
.byte 0x14+0x00 |
.byte 0xf0+0x01 |
.byte 0x3c+0x00 |
.byte 0x28+0x00 |
.byte 0xe4+0x01 |
.byte 0xa0+0x01 |
.byte 0x6c+0x00 |
.byte 0x78+0x00 |
.byte 0xb4+0x01 |
.byte 0x50+0x00 |
.byte 0x9c+0x01 |
.byte 0x88+0x01 |
.byte 0x44+0x00 |
/* ---------------------------------------------------------------------- *\ |
#!/usr/bin/python |
for crc in range(16): |
for bit in range(4): |
xor = crc & 1 |
crc >>= 1 |
if xor: |
crc ^= 0xA001 # X^16 + X^15 + X^2 + 1 (reversed) |
print "\t.byte\t0x%02x+0x%02x" % (crc >> 8, crc & 0xff) |
\* ---------------------------------------------------------------------- */ |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/def.h |
---|
0,0 → 1,74 |
// ====================================================================== |
// Common definitions for the USB driver |
// |
// Copyright (C) 2006 Dick Streefland |
// |
// This is free software, licensed under the terms of the GNU General |
// Public License as published by the Free Software Foundation. |
// ====================================================================== |
#ifdef __ASSEMBLER__ |
#define __SFR_OFFSET 0 |
#endif |
#include <avr/io.h> |
#include "usbtiny.h" |
// Preprocessor magic |
#define CAT2(a,b) CAT2EXP(a, b) |
#define CAT2EXP(a,b) a ## b |
#define CAT3(a,b,c) CAT3EXP(a, b, c) |
#define CAT3EXP(a,b,c) a ## b ## c |
// I/O Ports |
#define USB_IN CAT2(PIN, USBTINY_PORT) |
#define USB_OUT CAT2(PORT, USBTINY_PORT) |
#define USB_DDR CAT2(DDR, USBTINY_PORT) |
// I/O bit masks |
#define USB_MASK_DMINUS (1 << (USBTINY_DMINUS)) |
#define USB_MASK_DPLUS (1 << (USBTINY_DPLUS)) |
#define USB_MASK (USB_MASK_DMINUS | USB_MASK_DPLUS) |
// Interrupt configuration |
#if defined EICRA |
# define USB_INT_CONFIG EICRA |
#else |
# define USB_INT_CONFIG MCUCR |
#endif |
#define USB_INT_CONFIG_SET ((1 << CAT3(ISC,USBTINY_INT,1)) | (1 << CAT3(ISC,USBTINY_INT,0))) |
#if defined SIG_INT0 |
# define USB_INT_VECTOR CAT2(SIG_INT, USBTINY_INT) |
#else |
# define USB_INT_VECTOR CAT2(SIG_INTERRUPT, USBTINY_INT) |
#endif |
// Interrupt enable |
#if defined GIMSK |
# define USB_INT_ENABLE GIMSK |
#elif defined EIMSK |
# define USB_INT_ENABLE EIMSK |
#else |
# define USB_INT_ENABLE GICR |
#endif |
#define USB_INT_ENABLE_BIT CAT2(INT,USBTINY_INT) |
// Interrupt pending bit |
#if defined EIFR |
# define USB_INT_PENDING EIFR |
#else |
# define USB_INT_PENDING GIFR |
#endif |
#define USB_INT_PENDING_BIT CAT2(INTF,USBTINY_INT) |
// USB PID values |
#define USB_PID_SETUP 0x2d |
#define USB_PID_OUT 0xe1 |
#define USB_PID_IN 0x69 |
#define USB_PID_DATA0 0xc3 |
#define USB_PID_DATA1 0x4b |
#define USB_PID_ACK 0xd2 |
#define USB_PID_NAK 0x5a |
#define USB_PID_STALL 0x1e |
// Various constants |
#define USB_BUFSIZE 11 // PID + data + CRC |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/int.S |
---|
0,0 → 1,562 |
; ====================================================================== |
; USB interrupt handler |
; |
; This is the handler for the interrupt caused by the initial rising edge |
; on the D+ USB signal. The NRZI encoding and bit stuffing are removed, |
; and the packet is saved in one of the two input buffers. In some cases, |
; a reply packet is sent right away. |
; |
; When a DATA0/DATA1 packet directly follows a SETUP or OUT packet, while |
; this interrupt handler is not yet finished, there would be no time to |
; return and take another interrupt. In that case, the second packet is |
; decoded directly in the same invocation. |
; |
; This code is *extremely* time critical. For instance, there is not a |
; single spare cycle in the receiver loop, and only two in the transmitter |
; loop. In addition, the various code paths are laid out in such a way that |
; the various USB timeouts are not violated, in particular the maximum time |
; between the reception of a packet and the reply, which is 6.5 bit times |
; for a detachable cable (TRSPIPD1), and 7.5 bit times for a captive cable |
; (TRSPIPD2). The worst-case delay here is 51 cycles, which is just below |
; the 52 cycles for a detachable cable. |
; |
; The interrupt handler must be reached within 34 cycles after D+ goes high |
; for the first time, so the interrupts should not be disabled for longer |
; than 34-4-2=28 cycles. |
; |
; The end-of-packet (EOP) is sampled in the second bit, because the USB |
; standard allows the EOP to be delayed by up to one bit. As the EOP |
; duration is two bits, this is not a problem. |
; |
; Stack usage including the return address: 11 bytes. |
; |
; Copyright (C) 2006 Dick Streefland |
; |
; This is free software, licensed under the terms of the GNU General |
; Public License as published by the Free Software Foundation. |
; ====================================================================== |
#include "def.h" |
; ---------------------------------------------------------------------- |
; local data |
; ---------------------------------------------------------------------- |
.data |
tx_ack: .byte USB_PID_ACK ; ACK packet |
tx_nak: .byte USB_PID_NAK ; NAK packet |
.lcomm token_pid, 1 ; PID of most recent token packet |
; ---------------------------------------------------------------------- |
; register definitions |
; ---------------------------------------------------------------------- |
// receiver: |
#define count r16 |
#define usbmask r17 |
#define odd r18 |
#define byte r19 |
#define fixup r20 |
#define even r22 |
// transmitter: |
#define output odd |
#define done fixup |
#define next even |
// control: |
#define pid odd |
#define addr usbmask |
#define tmp fixup |
#define nop2 rjmp .+0 // not .+2 for some strange reason |
; ---------------------------------------------------------------------- |
; interrupt handler |
; ---------------------------------------------------------------------- |
.text |
.global USB_INT_VECTOR |
.type USB_INT_VECTOR, @function |
; ---------------------------------------------------------------------- |
; This handler must be reached no later than 34 cycles after D+ goes high |
; for the first time. |
; ---------------------------------------------------------------------- |
USB_INT_VECTOR: |
; save registers |
push count |
push usbmask |
push odd |
push YH |
push YL |
in count, SREG |
push count |
; ---------------------------------------------------------------------- |
; Synchronize to the pattern 10101011 on D+. This code must be reached |
; no later than 47 cycles after D+ goes high for the first time. |
; ---------------------------------------------------------------------- |
sync: |
; wait until D+ == 0 |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync ; jump if D+ == 1 |
resync: |
; sync on 0-->1 transition on D+ with a 2 cycle resolution |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync6 ; jump if D+ == 1 |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync6 ; jump if D+ == 1 |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync6 ; jump if D+ == 1 |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync6 ; jump if D+ == 1 |
sbic USB_IN, USBTINY_DPLUS |
rjmp sync6 ; jump if D+ == 1 |
ldi count, 1<<USB_INT_PENDING_BIT |
out USB_INT_PENDING, count |
rjmp return ; ==> false start, bail out |
sync6: |
; we are now between -1 and +1 cycle from the center of the bit |
; following the 0-->1 transition |
lds YL, usb_rx_off |
clr YH |
subi YL, lo8(-(usb_rx_buf)) ; Y = & usb_rx_buf[usb_rx_off] |
sbci YH, hi8(-(usb_rx_buf)) |
ldi count, USB_BUFSIZE ; limit on number of bytes to receive |
ldi usbmask, USB_MASK ; why is there no eori instruction? |
ldi odd, USB_MASK_DPLUS |
sync7: |
; the last sync bit should also be 1 |
sbis USB_IN, USBTINY_DPLUS ; bit 7 of sync byte? |
rjmp resync ; no, wait for next transition |
push byte |
push fixup |
push even |
; ---------------------------------------------------------------------- |
; receiver loop |
; ---------------------------------------------------------------------- |
in even, USB_IN ; sample bit 0 |
ldi byte, 0x80 ; load sync byte for correct unstuffing |
rjmp rxentry ; 2 cycles |
rxloop: |
in even, USB_IN ; sample bit 0 |
or fixup, byte |
st Y+, fixup ; 2 cycles |
rxentry: |
clr fixup |
andi even, USB_MASK |
eor odd, even |
subi odd, 1 |
in odd, USB_IN ; sample bit 1 |
andi odd, USB_MASK |
breq eop ; ==> EOP detected |
ror byte |
cpi byte, 0xfc |
brcc skip0 |
skipped0: |
eor even, odd |
subi even, 1 |
in even, USB_IN ; sample bit 2 |
andi even, USB_MASK |
ror byte |
cpi byte, 0xfc |
brcc skip1 |
skipped1: |
eor odd, even |
subi odd, 1 |
ror byte |
in odd, USB_IN ; sample bit 3 |
andi odd, USB_MASK |
cpi byte, 0xfc |
brcc skip2 |
eor even, odd |
subi even, 1 |
ror byte |
skipped2: |
cpi byte, 0xfc |
in even, USB_IN ; sample bit 4 |
andi even, USB_MASK |
brcc skip3 |
eor odd, even |
subi odd, 1 |
ror byte |
skipped4: |
cpi byte, 0xfc |
skipped3: |
brcc skip4 |
in odd, USB_IN ; sample bit 5 |
andi odd, USB_MASK |
eor even, odd |
subi even, 1 |
ror byte |
skipped5: |
cpi byte, 0xfc |
brcc skip5 |
dec count |
in even, USB_IN ; sample bit 6 |
brmi overflow ; ==> overflow |
andi even, USB_MASK |
eor odd, even |
subi odd, 1 |
ror byte |
skipped6: |
cpi byte, 0xfc |
brcc skip6 |
in odd, USB_IN ; sample bit 7 |
andi odd, USB_MASK |
eor even, odd |
subi even, 1 |
ror byte |
cpi byte, 0xfc |
brcs rxloop ; 2 cycles |
rjmp skip7 |
eop: |
rjmp eop2 |
overflow: |
rjmp ignore |
; ---------------------------------------------------------------------- |
; out-of-line code to skip stuffing bits |
; ---------------------------------------------------------------------- |
skip0: ; 1+6 cycles |
eor even, usbmask |
in odd, USB_IN ; resample bit 1 |
andi odd, USB_MASK |
cbr byte, (1<<7) |
sbr fixup, (1<<0) |
rjmp skipped0 |
skip1: ; 2+5 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<1) |
in even, USB_IN ; resample bit 2 |
andi even, USB_MASK |
eor odd, usbmask |
rjmp skipped1 |
skip2: ; 3+7 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<2) |
eor even, usbmask |
in odd, USB_IN ; resample bit 3 |
andi odd, USB_MASK |
eor even, odd |
subi even, 1 |
ror byte |
rjmp skipped2 |
skip3: ; 4+7 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<3) |
eor odd, usbmask |
ori byte, 1 |
in even, USB_IN ; resample bit 4 |
andi even, USB_MASK |
eor odd, even |
subi odd, 1 |
ror byte |
rjmp skipped3 |
skip4: ; 5 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<4) |
eor even, usbmask |
rjmp skipped4 |
skip5: ; 5 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<5) |
eor odd, usbmask |
rjmp skipped5 |
skip6: ; 5 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<6) |
eor even, usbmask |
rjmp skipped6 |
skip7: ; 7 cycles |
cbr byte, (1<<7) |
sbr fixup, (1<<7) |
eor odd, usbmask |
nop2 |
rjmp rxloop |
; ---------------------------------------------------------------------- |
; end-of-packet detected (worst-case: 3 cycles after end of SE0) |
; ---------------------------------------------------------------------- |
eop2: |
; clear pending interrupt (SE0+3) |
ldi byte, 1<<USB_INT_PENDING_BIT |
out USB_INT_PENDING, byte ; clear pending bit at end of packet |
; ignore packets shorter than 3 bytes |
subi count, USB_BUFSIZE |
neg count ; count = packet length |
cpi count, 3 |
brlo ignore |
; get PID |
sub YL, count |
ld pid, Y |
; check for DATA0/DATA1 first, as this is the critical path (SE0+12) |
cpi pid, USB_PID_DATA0 |
breq is_data ; handle DATA0 packet |
cpi pid, USB_PID_DATA1 |
breq is_data ; handle DATA1 packet |
; check ADDR (SE0+16) |
ldd addr, Y+1 |
andi addr, 0x7f |
lds tmp, usb_address |
cp addr, tmp ; is this packet for me? |
brne ignore ; no, ignore |
; check for other PIDs (SE0+23) |
cpi pid, USB_PID_IN |
breq is_in ; handle IN packet |
cpi pid, USB_PID_SETUP |
breq is_setup_out ; handle SETUP packet |
cpi pid, USB_PID_OUT |
breq is_setup_out ; handle OUT packet |
; ---------------------------------------------------------------------- |
; exit point for ignored packets |
; ---------------------------------------------------------------------- |
ignore: |
clr tmp |
sts token_pid, tmp |
pop even |
pop fixup |
pop byte |
rjmp return |
; ---------------------------------------------------------------------- |
; Handle SETUP/OUT (SE0+30) |
; ---------------------------------------------------------------------- |
is_setup_out: |
sts token_pid, pid ; save PID of token packet |
pop even |
pop fixup |
pop byte |
in count, USB_INT_PENDING ; next packet already started? |
sbrc count, USB_INT_PENDING_BIT |
rjmp sync ; yes, get it right away (SE0+42) |
; ---------------------------------------------------------------------- |
; restore registers and return from interrupt |
; ---------------------------------------------------------------------- |
return: |
pop count |
out SREG, count |
pop YL |
pop YH |
pop odd |
pop usbmask |
pop count |
reti |
; ---------------------------------------------------------------------- |
; Handle IN (SE0+26) |
; ---------------------------------------------------------------------- |
is_in: |
lds count, usb_tx_len |
tst count ; data ready? |
breq nak ; no, reply with NAK |
lds tmp, usb_rx_len |
tst tmp ; unprocessed input packet? |
brne nak ; yes, don't send old data for new packet |
sts usb_tx_len, tmp ; buffer is available again (after reti) |
ldi YL, lo8(usb_tx_buf) |
ldi YH, hi8(usb_tx_buf) |
rjmp send_packet ; SE0+40, SE0 --> SOP <= 51 |
; ---------------------------------------------------------------------- |
; Handle DATA0/DATA1 (SE0+17) |
; ---------------------------------------------------------------------- |
is_data: |
lds pid, token_pid |
tst pid ; data following our SETUP/OUT |
breq ignore ; no, ignore |
lds tmp, usb_rx_len |
tst tmp ; buffer free? |
brne nak ; no, reply with NAK |
sts usb_rx_len, count ; pass buffer length |
sts usb_rx_token, pid ; pass PID of token (SETUP or OUT) |
lds count, usb_rx_off ; switch to other input buffer |
ldi tmp, USB_BUFSIZE |
sub tmp, count |
sts usb_rx_off, tmp |
; ---------------------------------------------------------------------- |
; send ACK packet (SE0+35) |
; ---------------------------------------------------------------------- |
ack: |
ldi YL, lo8(tx_ack) |
ldi YH, hi8(tx_ack) |
rjmp send_token |
; ---------------------------------------------------------------------- |
; send NAK packet (SE0+36) |
; ---------------------------------------------------------------------- |
nak: |
ldi YL, lo8(tx_nak) |
ldi YH, hi8(tx_nak) |
send_token: |
ldi count, 1 ; SE0+40, SE0 --> SOP <= 51 |
; ---------------------------------------------------------------------- |
; acquire the bus and send a packet (11 cycles to SOP) |
; ---------------------------------------------------------------------- |
send_packet: |
in output, USB_OUT |
cbr output, USB_MASK |
ori output, USB_MASK_DMINUS |
in usbmask, USB_DDR |
ori usbmask, USB_MASK |
out USB_OUT, output ; idle state |
out USB_DDR, usbmask ; acquire bus |
ldi usbmask, USB_MASK |
ldi byte, 0x80 ; start with sync byte |
; ---------------------------------------------------------------------- |
; transmitter loop |
; ---------------------------------------------------------------------- |
txloop: |
sbrs byte, 0 |
eor output, usbmask |
out USB_OUT, output ; output bit 0 |
ror byte |
ror done |
stuffed0: |
cpi done, 0xfc |
brcc stuff0 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
stuffed1: |
out USB_OUT, output ; output bit 1 |
ror done |
cpi done, 0xfc |
brcc stuff1 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
nop |
stuffed2: |
out USB_OUT, output ; output bit 2 |
ror done |
cpi done, 0xfc |
brcc stuff2 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
nop |
stuffed3: |
out USB_OUT, output ; output bit 3 |
ror done |
cpi done, 0xfc |
brcc stuff3 |
sbrs byte, 0 |
eor output, usbmask |
ld next, Y+ ; 2 cycles |
out USB_OUT, output ; output bit 4 |
ror byte |
ror done |
stuffed4: |
cpi done, 0xfc |
brcc stuff4 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
stuffed5: |
out USB_OUT, output ; output bit 5 |
ror done |
cpi done, 0xfc |
brcc stuff5 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
stuffed6: |
ror done |
out USB_OUT, output ; output bit 6 |
cpi done, 0xfc |
brcc stuff6 |
sbrs byte, 0 |
eor output, usbmask |
ror byte |
mov byte, next |
stuffed7: |
ror done |
out USB_OUT, output ; output bit 7 |
cpi done, 0xfc |
brcc stuff7 |
dec count |
brpl txloop ; 2 cycles |
rjmp gen_eop |
; ---------------------------------------------------------------------- |
; out-of-line code to insert stuffing bits |
; ---------------------------------------------------------------------- |
stuff0: ; 2+3 |
eor output, usbmask |
clr done |
out USB_OUT, output |
rjmp stuffed0 |
stuff1: ; 3 |
eor output, usbmask |
rjmp stuffed1 |
stuff2: ; 3 |
eor output, usbmask |
rjmp stuffed2 |
stuff3: ; 3 |
eor output, usbmask |
rjmp stuffed3 |
stuff4: ; 2+3 |
eor output, usbmask |
clr done |
out USB_OUT, output |
rjmp stuffed4 |
stuff5: ; 3 |
eor output, usbmask |
rjmp stuffed5 |
stuff6: ; 3 |
eor output, usbmask |
rjmp stuffed6 |
stuff7: ; 3 |
eor output, usbmask |
rjmp stuffed7 |
; ---------------------------------------------------------------------- |
; generate EOP, release the bus, and return from interrupt |
; ---------------------------------------------------------------------- |
gen_eop: |
cbr output, USB_MASK |
out USB_OUT, output ; output SE0 for 2 bit times |
pop even |
pop fixup |
pop byte |
ldi count, 1<<USB_INT_PENDING_BIT |
out USB_INT_PENDING, count ; interrupt was triggered by transmit |
pop YH ; this is the saved SREG |
pop YL |
in usbmask, USB_DDR |
mov count, output |
ori output, USB_MASK_DMINUS |
out USB_OUT, output ; output J state for 1 bit time |
cbr usbmask, USB_MASK |
out SREG, YH |
pop YH |
pop odd ; is the same register as output! |
nop |
out USB_DDR, usbmask ; release bus |
out USB_OUT, count ; disable D- pullup |
pop usbmask |
pop count |
reti |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/usb.c |
---|
0,0 → 1,418 |
// ====================================================================== |
// USB driver |
// |
// Entry points: |
// usb_init() - enable the USB interrupt |
// usb_poll() - poll for incoming packets and process them |
// |
// This code communicates with the interrupt handler through a number of |
// global variables, including two input buffers and one output buffer. |
// Packets are queued for transmission by copying them into the output |
// buffer. The interrupt handler will transmit such a packet on the |
// reception of an IN packet. |
// |
// Standard SETUP packets are handled here. Non-standard SETUP packets |
// are forwarded to the application code by calling usb_setup(). The |
// macros USBTINY_CALLBACK_IN and USBTINY_CALLBACK_OUT control whether |
// the callback functions usb_in() and usb_out() will be called for IN |
// and OUT transfers. |
// |
// Maximum stack usage (gcc 3.4.3 & 4.1.0) of usb_poll(): 5 bytes plus |
// possible additional stack usage in usb_setup(), usb_in() or usb_out(). |
// |
// Copyright (C) 2006 Dick Streefland |
// |
// This is free software, licensed under the terms of the GNU General |
// Public License as published by the Free Software Foundation. |
// ====================================================================== |
#include <avr/pgmspace.h> |
#include <avr/interrupt.h> |
#include "def.h" |
#include "usb.h" |
#define LE(word) (word) & 0xff, (word) >> 8 |
// ---------------------------------------------------------------------- |
// USB constants |
// ---------------------------------------------------------------------- |
enum |
{ |
DESCRIPTOR_TYPE_DEVICE = 1, |
DESCRIPTOR_TYPE_CONFIGURATION, |
DESCRIPTOR_TYPE_STRING, |
DESCRIPTOR_TYPE_INTERFACE, |
DESCRIPTOR_TYPE_ENDPOINT, |
}; |
// ---------------------------------------------------------------------- |
// Interrupt handler interface |
// ---------------------------------------------------------------------- |
byte_t usb_rx_buf[2*USB_BUFSIZE]; // two input buffers |
byte_t usb_rx_off; // buffer offset: 0 or USB_BUFSIZE |
byte_t usb_rx_len; // buffer size, 0 means empty |
byte_t usb_rx_token; // PID of token packet: SETUP or OUT |
byte_t usb_tx_buf[USB_BUFSIZE]; // output buffer |
byte_t usb_tx_len; // output buffer size, 0 means empty |
byte_t usb_address; // assigned USB address |
// ---------------------------------------------------------------------- |
// Local data |
// ---------------------------------------------------------------------- |
enum |
{ |
TX_STATE_IDLE = 0, // transmitter idle |
TX_STATE_RAM, // usb_tx_data is a RAM address |
TX_STATE_ROM, // usb_tx_data is a ROM address |
TX_STATE_CALLBACK, // call usb_in() to obtain transmit data |
}; |
static byte_t usb_tx_state; // TX_STATE_*, see enum above |
static byte_t usb_tx_total; // total transmit size |
static byte_t* usb_tx_data; // pointer to data to transmit |
static byte_t new_address; // new device address |
#if defined USBTINY_VENDOR_NAME |
struct |
{ |
byte_t length; |
byte_t type; |
int string[sizeof(USBTINY_VENDOR_NAME)-1]; |
} string_vendor PROGMEM = |
{ |
2 * sizeof(USBTINY_VENDOR_NAME), |
DESCRIPTOR_TYPE_STRING, |
{ CAT2(L, USBTINY_VENDOR_NAME) } |
}; |
# define VENDOR_NAME_ID 1 |
#else |
# define VENDOR_NAME_ID 0 |
#endif |
#if defined USBTINY_DEVICE_NAME |
struct |
{ |
byte_t length; |
byte_t type; |
int string[sizeof(USBTINY_DEVICE_NAME)-1]; |
} string_device PROGMEM = |
{ |
2 * sizeof(USBTINY_DEVICE_NAME), |
DESCRIPTOR_TYPE_STRING, |
{ CAT2(L, USBTINY_DEVICE_NAME) } |
}; |
# define DEVICE_NAME_ID 2 |
#else |
# define DEVICE_NAME_ID 0 |
#endif |
#if defined USBTINY_SERIAL |
struct |
{ |
byte_t length; |
byte_t type; |
int string[sizeof(USBTINY_SERIAL)-1]; |
} string_serial PROGMEM = |
{ |
2 * sizeof(USBTINY_SERIAL), |
DESCRIPTOR_TYPE_STRING, |
{ CAT2(L, USBTINY_SERIAL) } |
}; |
# define SERIAL_ID 3 |
#else |
# define SERIAL_ID 0 |
#endif |
#if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID |
static byte_t string_langid [] PROGMEM = |
{ |
4, // bLength |
DESCRIPTOR_TYPE_STRING, // bDescriptorType (string) |
LE(0x0409), // wLANGID[0] (American English) |
}; |
#endif |
// Device Descriptor |
static byte_t descr_device [18] PROGMEM = |
{ |
18, // bLength |
DESCRIPTOR_TYPE_DEVICE, // bDescriptorType |
LE(0x0110), // bcdUSB |
USBTINY_DEVICE_CLASS, // bDeviceClass |
USBTINY_DEVICE_SUBCLASS, // bDeviceSubClass |
USBTINY_DEVICE_PROTOCOL, // bDeviceProtocol |
8, // bMaxPacketSize0 |
LE(USBTINY_VENDOR_ID), // idVendor |
LE(USBTINY_DEVICE_ID), // idProduct |
LE(USBTINY_DEVICE_VERSION), // bcdDevice |
VENDOR_NAME_ID, // iManufacturer |
DEVICE_NAME_ID, // iProduct |
SERIAL_ID, // iSerialNumber |
1, // bNumConfigurations |
}; |
// Configuration Descriptor |
static byte_t descr_config [] PROGMEM = |
{ |
9, // bLength |
DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType |
LE(9+9+7*USBTINY_ENDPOINT), // wTotalLength |
1, // bNumInterfaces |
1, // bConfigurationValue |
0, // iConfiguration |
(USBTINY_MAX_POWER ? 0x80 : 0xc0), // bmAttributes |
(USBTINY_MAX_POWER + 1) / 2, // MaxPower |
// Standard Interface Descriptor |
9, // bLength |
DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType |
0, // bInterfaceNumber |
0, // bAlternateSetting |
USBTINY_ENDPOINT, // bNumEndpoints |
USBTINY_INTERFACE_CLASS, // bInterfaceClass |
USBTINY_INTERFACE_SUBCLASS, // bInterfaceSubClass |
USBTINY_INTERFACE_PROTOCOL, // bInterfaceProtocol |
0, // iInterface |
#if USBTINY_ENDPOINT |
// Additional Endpoint |
7, // bLength |
DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType |
USBTINY_ENDPOINT_ADDRESS, // bEndpointAddress |
USBTINY_ENDPOINT_TYPE, // bmAttributes |
LE(8), // wMaxPacketSize |
USBTINY_ENDPOINT_INTERVAL, // bInterval |
#endif |
}; |
// ---------------------------------------------------------------------- |
// Inspect an incoming packet. |
// ---------------------------------------------------------------------- |
static void usb_receive ( byte_t* data, byte_t rx_len ) |
{ |
byte_t len; |
byte_t type; |
byte_t limit; |
usb_tx_state = TX_STATE_RAM; |
len = 0; |
if ( usb_rx_token == USB_PID_SETUP ) |
{ |
limit = data[6]; |
if ( data[7] ) |
{ |
limit = 255; |
} |
type = data[0] & 0x60; |
if ( type == 0x00 ) |
{ // Standard request |
if ( data[1] == 0 ) // GET_STATUS |
{ |
len = 2; |
#if USBTINY_MAX_POWER == 0 |
data[0] = (data[0] == 0x80); |
#else |
data[0] = 0; |
#endif |
data[1] = 0; |
} |
else if ( data[1] == 5 ) // SET_ADDRESS |
{ |
new_address = data[2]; |
} |
else if ( data[1] == 6 ) // GET_DESCRIPTOR |
{ |
usb_tx_state = TX_STATE_ROM; |
if ( data[3] == 1 ) |
{ // DEVICE |
data = (byte_t*) &descr_device; |
len = sizeof(descr_device); |
} |
else if ( data[3] == 2 ) |
{ // CONFIGURATION |
data = (byte_t*) &descr_config; |
len = sizeof(descr_config); |
} |
#if VENDOR_NAME_ID || DEVICE_NAME_ID || SERIAL_ID |
else if ( data[3] == 3 ) |
{ // STRING |
if ( data[2] == 0 ) |
{ |
data = (byte_t*) &string_langid; |
len = sizeof(string_langid); |
} |
#if VENDOR_NAME_ID |
else if ( data[2] == VENDOR_NAME_ID ) |
{ |
data = (byte_t*) &string_vendor; |
len = sizeof(string_vendor); |
} |
#endif |
#if DEVICE_NAME_ID |
else if ( data[2] == DEVICE_NAME_ID ) |
{ |
data = (byte_t*) &string_device; |
len = sizeof(string_device); |
} |
#endif |
#if SERIAL_ID |
else if ( data[2] == SERIAL_ID ) |
{ |
data = (byte_t*) &string_serial; |
len = sizeof(string_serial); |
} |
#endif |
} |
#endif |
} |
else if ( data[1] == 8 ) // GET_CONFIGURATION |
{ |
data[0] = 1; // return bConfigurationValue |
len = 1; |
} |
else if ( data[1] == 10 ) // GET_INTERFACE |
{ |
data[0] = 0; |
len = 1; |
} |
} |
else |
{ // Class or Vendor request |
len = usb_setup( data ); |
#if USBTINY_CALLBACK_IN |
if ( len == 0xff ) |
{ |
usb_tx_state = TX_STATE_CALLBACK; |
} |
#endif |
} |
if ( len > limit ) |
{ |
len = limit; |
} |
usb_tx_data = data; |
} |
#if USBTINY_CALLBACK_OUT |
else if ( rx_len > 0 ) |
{ // usb_rx_token == USB_PID_OUT |
usb_out( data, rx_len ); |
} |
#endif |
usb_tx_total = len; |
usb_tx_buf[0] = USB_PID_DATA0; // next data packet will be DATA1 |
} |
// ---------------------------------------------------------------------- |
// Load the transmit buffer with the next packet. |
// ---------------------------------------------------------------------- |
static void usb_transmit ( void ) |
{ |
byte_t len; |
byte_t* src; |
byte_t* dst; |
byte_t i; |
byte_t b; |
usb_tx_buf[0] ^= (USB_PID_DATA0 ^ USB_PID_DATA1); |
len = usb_tx_total; |
if ( len > 8 ) |
{ |
len = 8; |
} |
dst = usb_tx_buf + 1; |
if ( len > 0 ) |
{ |
#if USBTINY_CALLBACK_IN |
if ( usb_tx_state == TX_STATE_CALLBACK ) |
{ |
len = usb_in( dst, len ); |
} |
else |
#endif |
{ |
src = usb_tx_data; |
if ( usb_tx_state == TX_STATE_RAM ) |
{ |
for ( i = 0; i < len; i++ ) |
{ |
*dst++ = *src++; |
} |
} |
else // usb_tx_state == TX_STATE_ROM |
{ |
for ( i = 0; i < len; i++ ) |
{ |
b = pgm_read_byte( src ); |
src++; |
*dst++ = b; |
} |
} |
usb_tx_data = src; |
} |
usb_tx_total -= len; |
} |
crc( usb_tx_buf + 1, len ); |
usb_tx_len = len + 3; |
if ( len < 8 ) |
{ // this is the last packet |
usb_tx_state = TX_STATE_IDLE; |
} |
} |
// ---------------------------------------------------------------------- |
// Initialize the low-level USB driver. |
// ---------------------------------------------------------------------- |
extern void usb_init ( void ) |
{ |
USB_INT_CONFIG |= USB_INT_CONFIG_SET; |
USB_INT_ENABLE |= (1 << USB_INT_ENABLE_BIT); |
sei(); |
} |
// ---------------------------------------------------------------------- |
// Poll USB driver: |
// - check for incoming USB packets |
// - refill an empty transmit buffer |
// - check for USB bus reset |
// ---------------------------------------------------------------------- |
extern void usb_poll ( void ) |
{ |
byte_t i; |
// check for incoming USB packets |
if ( usb_rx_len != 0 ) |
{ |
usb_receive( usb_rx_buf + USB_BUFSIZE - usb_rx_off + 1, usb_rx_len - 3 ); |
usb_tx_len = 0; // abort pending transmission |
usb_rx_len = 0; // accept next packet |
} |
// refill an empty transmit buffer, when the transmitter is active |
if ( usb_tx_len == 0 ) |
{ |
if ( usb_tx_state != TX_STATE_IDLE ) |
{ |
usb_transmit(); |
} |
else |
{ // change the USB address at the end of a transfer |
usb_address = new_address; |
} |
} |
// check for USB bus reset |
for ( i = 10; i > 0 && ! (USB_IN & USB_MASK_DMINUS); i-- ) |
{ |
} |
if ( i == 0 ) |
{ // SE0 for more than 2.5uS is a reset |
cli(); |
usb_tx_len=0; |
usb_rx_len=0; |
new_address = 0; |
sei(); |
} |
} |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny/usb.h |
---|
0,0 → 1,28 |
// ====================================================================== |
// Public interface of the USB driver |
// |
// Copyright (C) 2006 Dick Streefland |
// |
// This is free software, licensed under the terms of the GNU General |
// Public License as published by the Free Software Foundation. |
// ====================================================================== |
#ifndef USB_H |
#define USB_H |
typedef unsigned char byte_t; |
typedef unsigned int uint_t; |
// usb.c |
extern void usb_init ( void ); |
extern void usb_poll ( void ); |
// crc.S |
extern void crc ( byte_t* data, byte_t len ); |
// application callback functions |
extern byte_t usb_setup ( byte_t data[8] ); |
extern void usb_out ( byte_t* data, byte_t len ); |
extern byte_t usb_in ( byte_t* data, byte_t len ); |
#endif // USB_H |
/Designs/Tools/i2c_AVR_USB/SW/firmware/usbtiny.h |
---|
0,0 → 1,83 |
// ====================================================================== |
// USBtiny Configuration |
// |
// Copyright (C) 2006 Dick Streefland |
// |
// This is free software, licensed under the terms of the GNU General |
// Public License as published by the Free Software Foundation. |
// ====================================================================== |
// The D+ and D- USB signals should be connected to two pins of the same |
// I/O port. The following macros define the port letter and the input |
// bit numbers: |
#if! defined (__AVR_ATtiny45__) |
#define USBTINY_PORT C |
#define USBTINY_DPLUS 1 |
#define USBTINY_DMINUS 0 |
#else |
#define USBTINY_PORT B |
#define USBTINY_DPLUS 2 |
#define USBTINY_DMINUS 0 |
#endif |
// The D+ signal should be connected to an interrupt input to trigger an |
// interrupt at the start of a packet. When you use the same pin for the |
// D+ USB signal and the interrupt input, only two I/O pins are needed |
// for the USB interface. The following macro defines the interrupt |
// number: |
#define USBTINY_INT 0 |
// The power requirement of the USB device in mA, or 0 when the device |
// is not bus powered: |
#define USBTINY_MAX_POWER 10 |
// The USB vendor and device IDs. These values should be unique for |
// every distinct device. You can get your own vendor ID from the USB |
// Implementers Forum (www.usb.org) if you have a spare $1500 to kill. |
// Alternatively, you can buy a small range of device IDs from |
// www.voti.nl or www.mecanique.co.uk, or be naughty and use something |
// else, like for instance product ID 0x6666, which is registered as |
// "Prototype product Vendor ID". |
#define USBTINY_VENDOR_ID 0x0403 |
#define USBTINY_DEVICE_ID 0xc631 |
// The version of the device as a 16-bit number: 256*major + minor. |
#define USBTINY_DEVICE_VERSION 0x205 |
// The following optional macros may be used as an identification of |
// your device. Undefine them when you run out of flash space. |
#define USBTINY_VENDOR_NAME "Till Harbaum" |
#define USBTINY_DEVICE_NAME "i2c-tiny-usb" |
#undef USBTINY_SERIAL |
// Define the device class, subclass and protocol. Device class 0xff |
// is "vendor specific". |
#define USBTINY_DEVICE_CLASS 0xff |
#define USBTINY_DEVICE_SUBCLASS 0 |
#define USBTINY_DEVICE_PROTOCOL 0 |
// Define the interface class, subclass and protocol. Interface class |
// 0xff is "vendor specific". |
#define USBTINY_INTERFACE_CLASS 0xff |
#define USBTINY_INTERFACE_SUBCLASS 0 |
#define USBTINY_INTERFACE_PROTOCOL 0 |
// Normally, usb_setup() should write the reply of up to 8 bytes into the |
// packet buffer, and return the reply length. When this macro is defined |
// as 1, you have the option of returning 0xff instead. In that case, the |
// USB driver will call a function usb_in() to obtain the data to send |
// back to the host. This can be used to generate the data on-the-fly. |
#define USBTINY_CALLBACK_IN 1 |
// When this macro is defined as 0, OUT packets are simply ignored. |
// When defined as 1, the function usb_out() is called for OUT packets. |
// You need this option to send data from the host to the device in |
// a control transfer. |
#define USBTINY_CALLBACK_OUT 1 |
// Set the macro USBTINY_ENDPOINT to 1 to add an additional endpoint, |
// according to the values of the three other macros. |
#define USBTINY_ENDPOINT 0 |
#define USBTINY_ENDPOINT_ADDRESS 0x81 // IN endpoint #1 |
#define USBTINY_ENDPOINT_TYPE 0x00 // control transfer type |
#define USBTINY_ENDPOINT_INTERVAL 0 // ignored |
/Designs/Tools/i2c_AVR_USB/SW/firmware/util/check.py |
---|
0,0 → 1,51 |
#!/usr/bin/python |
# ====================================================================== |
# check.py - Check section sizes and other constraints |
# |
# Copyright (C) 2006 Dick Streefland |
# |
# This is free software, licensed under the terms of the GNU General |
# Public License as published by the Free Software Foundation. |
# ====================================================================== |
import os, sys |
stacksize = 32 |
flashsize = 2048 |
ramsize = 128 |
if len(sys.argv) > 2: |
stacksize = int(sys.argv[2]) |
if len(sys.argv) > 3: |
flashsize = int(sys.argv[3]) |
if len(sys.argv) > 4: |
ramsize = int(sys.argv[4]) |
max_sram = ramsize - stacksize |
for line in os.popen('avr-objdump -ht ' + sys.argv[1]).readlines(): |
a = line.split() |
if len(a) == 7: |
if a[1] == '.text': |
text = int(a[2], 16) |
if a[1] == '.data': |
data = int(a[2], 16) |
if a[1] == '.bss': |
bss = int(a[2], 16) |
if len(a) == 5 and a[4] == 'crc4tab': |
crc4tab = int(a[0], 16) |
print 'text: %d, data: %d, bss: %d' % (text, data, bss) |
status = 0 |
overflow = text + data - flashsize |
if overflow > 0: |
print 'ERROR: Flash size limit exceeded by %d bytes.' % overflow |
status = 1 |
overflow = bss + data - max_sram |
if overflow > 0: |
print 'ERROR: SRAM size limit exceeded by %d bytes.' % overflow |
status = 1 |
if (crc4tab & 0xff) > 0xf0: |
print 'ERROR: The table crc4tab should not cross a page boundary.' |
status = 1 |
sys.exit(status) |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |