Showing posts with label LUFA. Show all posts
Showing posts with label LUFA. Show all posts

2011-03-15

AVR development with LUFA - TILTHW

  1. If you're going to switch between .USBSpecification = VERSION_BCD(01.10) and .USBSpecification = VERSION_BCD(02.00) and you're using a specific Windows driver (i.e. not HID, Mass Storage, etc.), then your device will only get installed properly until you reinstall that driver. Windows does not like having the USB specs of an existing device changed.

  2. The API changes quite a lot from release to release. Some would make a big deal out of it, but it really isn't. Just be careful that if you see an old LUFA guide, some of its calls might be obsolete. For instance some calls like EVENT_USB_Device_UnhandledControlRequest have been obsoleted.

  3. Stream serial debug output (printf) is easy once
    • you use the following in your source:
      #include <LUFA/Drivers/Peripheral/Serial.h>
      (...)
          Serial_Init(115200, true);
          Serial_CreateStream(NULL);
    • you make sure that $(LUFA_SRC_SERIAL) is referenced in your makefile sources (SRC = ...) along with $(LUFA_SRC_USB), as it is not included automatically.

  4. If you're getting undefined references to Endpoint_Read_Stream_LE and friends, you probably have LUFA_OPTS += -D CONTROL_ONLY_DEVICE defined in your makefile. Comment it out.

  5. On an AVR90USB162, there's only so much space that can be used for printf strings apparently, regardless of how much flash is being used. If you have too many serial debug statements, you may find that serial output is garbled until you eliminate some of them. Make sure you only use serial debug sparingly.

  6. EVENT_USB_Device_ConfigurationChanged() is NOT a good place to do serial debug output statement.

  7. If you are using multiple interfaces on Windows, you DO want to add a delay in EVENT_USB_Device_ConfigurationChanged()

  8. Use NULL as last parameter in the EP R/W calls (eg. Endpoint_Read_Stream_LE), unless you want to open a big bag of hurt!

  9. If you're using the same endpoint number for IN and OUT (eg. 0x01 & 0x81), you need to use Endpoint_SetEndpointDirection() to toggle the direction after selecting the EP. Oh, and don't use ENDPOINT_DESCRIPTOR_DIR_IN or ENDPOINT_DESCRIPTOR_DIR_OUT, use ENDPOINT_DIR_IN and ENDPOINT_DIR_OUT instead.

2011-03-11

Atmel AVR USB - Using LUFA with the AVR Studio 5 IDE

OK, so now we have our working makefile that builds our LUFA app using nothing but a DOS prompt and the AVR Studio 5 toolchain.

But how about being able to do both the development and compilation from the AVR Studio UI, to have something that resembles a serious development environment at last?

Supposedly the only step, since Atmel were kind enough to provide a conversion tool in AVRS5, is to convert the .aps file we got from LUFA and use the result. I'm still going to use the Joystick demo from the previous post to demonstrate that, since its makefile was fixed to work with AVRS5.


idiotic idiosyncrasies

So File -> Import AVR Studio 4 Project, then browse to the Demos\Device\ClassDriver\Joystick\Joystick.aps.
Now, if you don't select the right directory, Microsoft (this one's an MS idiotic idiosyncrasy, as they do the same in regular Visual Studio) will duplicate the files into a new location, instead of simply reusing the existing one. There's enough data duplication in the world already, so let's avoid that. The original source location is the location we want to use for the project.
So you thought that selecting the Demos\Device\ClassDriver\Joystick\ directory for the Solution Folder would do the trick? Wrong. Whatever you pick, Microsoft will create an extra subdirectory using the solution name in there, so if you use Demos\Device\ClassDriver\Joystick\, all the files will be duplicated into Demos\Device\ClassDriver\Joystick\Joystick\.
No bother then, you say, I'll just use Demos\Device\ClassDriver\ and AVR Studio will then pick up the existing Joystick\ directory and reuse the original files... My young little Padawan, you have a lot to learn about how people are hell bent on making sure convenience is unreachable in this world!

If you try that, you'll get the error:
Project Import Failed : The process cannot access the file 'D:\lufa-lib\Demos\Device\ClassDriver\Joystick\makefile' because it is being used by another process. [Activity : Converting AVR Studio 4 ExternalMakeFileSettings]

Yup, the whole process fails because the file that the process wants to modify is being accessed by the process itself. The thing is, either Atmel or MS is so adamant about duplicating files all over the place, for no good reason, that they haven't considered this really wild idea that someone would ever want not to duplicate the bloody file, and therefore fail to consider that if source and dest are the same, they shouldn't try to copy the files. This is so utterly idiotic!

The workaround? Actually use Demos\Device\ClassDriver\Joystick\ for the Solution Folder, so that the files are duplicated into a Joystick\ subdirectory, close AVR Studio, move the Joystick.avrgccproj file from Joystick\Joystick\ to Joystick\, and then manually edit the Joystick.avrsln file with a text editor and replace the "Joystick\Joystick.avrgccproj" reference there with "Joystick.avrgccproj".
Then delete the Joystick\ subdirectory, and you should be set as Nature (but not Microsoft) intended, i.e. with all of the solution, the project files and the source in the same single directory.

Once you've done that, you should be able to open your LUFA solution and get it to compile straight from AVRS5. Neat!

The only small issue that seems to exist is that when issuing "Rebuild Solution" in AVRS5, which calls "make clean all" behind the scenes, we run into the "opening dependency file .dep/Joystick.o.d: No such file or directory" error again. This seems to be a makefile issue, with the -include $(shell mkdir .dep) $(wildcard .dep/*) line being executed before the clean command, and thus not being able to re-create the .dep\ directory.

Atmel AVR USB - Starting with LUFA, using AVR Studio 5 and the commandline

That's right, we're going to do it the hard way (i.e. sans WinAVR) because we like it better when things don't work straight out of the box. If you don't want to patch stuff, just download WinAVR and be done with it.


I for one welcome our new LUFA overlords

LUFA is so easy to get started with (at least when using WinAVR), it should almost be illegal. I wish libusb would get there, but given our slow rate of getting anything that is convenient for users actually integrated, I doubt we ever will... Anyway, first order of the day is to get the latest LUFA, which we'll pick from SVN. Or you can just pick the latest zip archive from the official website but if you're using LUFA_101122 or earlier, please be aware that there is a bug with the Minimus implementation with regards to the HWB button. To clone from SVN, just have a look here.

Now, the interesting thing of course is, if you look in LUFA\Drivers\Board, you'll see that there is a MINIMUS directory. That means our current test board is supported straight out of the box. Yay!

There are a bunch of demos and projects as well, which is also where you measure the usefulness of a library (once again, unlike libusb, which chose to remove proposed samples, despite having a very limited supply of 'em included...). To test LUFA with the Minimus, we're going to pick the Joystick demo from Demos\Device\ClassDriver. Of course, we don't have a joystick on our board, and just one usable button, so that'll be a pretty limited "joystick", but Windows should still list the device, and if everything works as expected, we should be able to see our button presses in real-time in Windows device properties, so it's not that bad of a trade-off.


Minimus's minimal reconfiguration

The way you set things up for your target board in LUFA is by editing the relevant variables at the top of the makefile. If you go to the Demos\Device\ClassDriver\Joystick directory, you'll see that, apart from the source, you only have one makefile as well as Joystick.aps, which is the AVR Studio 4 project file that actually calls the makefile for compilation.

There's only very little we need to modify here. If you're using a Minimus board, here's what you want:
# MCU name
MCU = at90usb162

# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Target board
BOARD = MINIMUS

# Processor frequency.
F_CPU = 16000000


Compiling with AVR Studio 5 from the commandline

As pointed out earlier, we're not going to install WinAVR, because that would be too easy. We got a perfectly good avr-gcc toolchain installed with AVR Studio 5, so we might as well use it. Oh, and we're not going to use the AVR Studio 4 → AVR Studio 5 conversion process on the .aps just yet, because:
  1. You might be interested in using AVR Studio 5 for compilation outside of the GUI
  2. We will run into issues with the default makefile, that are better fixed first from the commandline, before moving to AVR Studio
Using AVR Studio from DOS prompt is actually very easy. You just need to add the following to your PATH System environmental variable (provided you used the default path during AVR Studio installation:
C:\Program Files (x86)\Atmel\AVR Studio 5.0\extensions\Application\AVR Toolchain\bin;
Once that's done, just open a prompt and navigate to the Joystick directory. Then run make, and...
D:\lufa-lib\Demos\Device\ClassDriver\Joystick>make
The system cannot find the path specified.
The system cannot find the path specified.
ECHO is off.
-------- begin --------
avr-gcc (AVR_8_bit_GNU_Toolchain_3.2.0_253) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

The system cannot find the path specified.
The system cannot find the path specified.
-f was unexpected at this time.
make: *** [sizebefore] Error 255
Dang!

I'll just cut to the chase here:
The "The system cannot find the path specified." occur whenever a "/dev/null" redirection is done in the Makefile. As to the "-f was unexpected at this time" (now, aren't you glad you found this blog), it occurs from the if test -f $(TARGET).elf statement that is done in "sizebefore:". That's right Dorothy, we're not using a UNIX shell anymore...
A quick glance at the "sizebefore:" and "sizeafter:" statements tell us that they're completely optional. So let's just remove them, which means that you must change the line:
# Default target.
all: begin gccversion sizebefore build sizeafter end
into:
# Default target.
all: begin gccversion build end
As well as remove these references in the:
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
section at the end of the file.


The Joystick's in the mind, man...

Let's try that again, shall we?
D:\lufa-lib\Demos\Device\ClassDriver\Joystick>make
The system cannot find the path specified.
The system cannot find the path specified.
ECHO is off.
-------- begin --------
avr-gcc (AVR_8_bit_GNU_Toolchain_3.2.0_253) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

The system cannot find the path specified.
The system cannot find the path specified.
-f was unexpected at this time.
make: *** [sizebefore] Error 255

D:\lufa-lib\Demos\Device\ClassDriver\Joystick>make
The system cannot find the path specified.
The system cannot find the path specified.
ECHO is off.
-------- begin --------
avr-gcc (AVR_8_bit_GNU_Toolchain_3.2.0_253) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ECHO is off.
Compiling C: Joystick.c
avr-gcc -c -mmcu=at90usb162 -I. -gdwarf-2 -DF_CPU=16000000UL -DF_CLOCK=16000000UL -DBOARD=BOARD_MINIMUS -DARCH=ARCH_AVR8 -D USB_DEVICE_ONLY -D FIXED_CONTROL_ENDPOINT_SIZE=8 -D FIXED_NUM_CONFIGURATIONS=1 -D USE_FLASH_DESCRIPTORS -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=./Joystick.lst -I../../../../ -std=c99 -MMD -MP -MF .dep/Joystick.o.d Joystick.c -o Joystick.o
In file included from Joystick.h:49:0,
                 from Joystick.c:37:
../../../../LUFA/Drivers/Board/Joystick.h:120:31: fatal error: Board/Joystick.h: No such file or directory
compilation terminated.
make: *** [Joystick.o] Error 1

That's a bit better. But yeah, the Board does indeed not define a joystick, so let's add a virtual one. The Joystick.h from LUFA\Drivers\Board\BUMBLEB will actually do just fine (it's using Port D but doesn't conflict with our LEDs or switches), so we just copy that file over to LUFA\Drivers\Board\MINIMUS. Ideally, you want to edit the __JOYSTICK_BUMBLEB_H__ macro in there to __JOYSTICK_MINIMUS_H__. Then you also need to edit LUFA\Drivers\Board\Joystick.h to add the lines:
        #elif (BOARD == BOARD_MINIMUS)
            #include "MINIMUS/Joystick.h"
Alrighty, let's try again...


"Come on makefile, you used to be cool!"
D:\lufa-lib\Demos\Device\ClassDriver\Joystick>make
The system cannot find the path specified.
The system cannot find the path specified.
ECHO is off.
-------- begin --------
avr-gcc (AVR_8_bit_GNU_Toolchain_3.2.0_253) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ECHO is off.
Compiling C: Joystick.c
avr-gcc -c -mmcu=at90usb162 -I. -gdwarf-2 -DF_CPU=16000000UL -DF_CLOCK=16000000UL -DBOARD=BOARD_MINIMUS -DARCH=ARCH_AVR8 -D USB_DEVICE_ONLY -D FIXED_CONTROL_ENDPOINT_SIZE=8 -D FIXED_NUM_CONFIGURATIONS=1 -D USE_FLASH_DESCRIPTORS -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=./Joystick.lst -I../../../../ -std=c99 -MMD -MP -MF .dep/Joystick.o.d Joystick.c -o Joystick.o
Joystick.c:188:1: fatal error: opening dependency file .dep/Joystick.o.d: No such file or directory
compilation terminated.
make: *** [Joystick.o] Error 1
Ah, that dreaded "fatal error: opening dependency file .dep/Joystick.o.d: No such file or directory" error...
Once again, to cut to the chase, you'll notice that we haven't fixed the "The system cannot find the path specified." /dev/null errors. Well, what do you know, the dependency problems actually comes from the .dep directory creation step not being able to execute because it references /dev/null.
The fix is simple (though output polluting): In the makefile, change the following:
# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)

# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
into:
# Create object files directory
$(shell mkdir $(OBJDIR))

# Include the dependency files.
-include $(shell mkdir .dep) $(wildcard .dep/*)

Try again.
(...)
ECHO is off.
Creating load file for Flash: Joystick.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock Joystick.elf Joystick.hex
ECHO is off.
Creating load file for EEPROM: Joystick.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
        --change-section-lma .eeprom=0 --no-change-warnings -O ihex Joystick.elf Joystick.eep || exit 0
ECHO is off.
Creating Extended Listing: Joystick.lss
avr-objdump -h -S -z Joystick.elf > Joystick.lss
ECHO is off.
Creating Symbol Table: Joystick.sym
avr-nm -n Joystick.elf > Joystick.sym
--------  end  --------
Yes, we have our hex file!! The system works!
If you flash the hex, you should now get a nice little "LUFA Joystick Demo" in your devices, and if you go to the Game controller settings → Properties, you should be able to see the status of the HWB button in realtime.

Now, using AVR Studio 5 with LUFA wasn't that difficult after all was it?
In the next post, I'll show you how to run everything from the AVR Studio UI, so that you're all set for LUFA development.