Problems with HIDkeys on atmega32 @WinXP

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
z0ttel

Problems with HIDkeys on atmega32 @WinXP

Post by z0ttel » Wed Dec 26, 2007 8:16 pm

Hi there,

I'm trying to get the HIDkeys project running on an atmega32, but the device doesn't gets recognized by the pc (running with WinXP SP2):
if I connect the the device, the USB logo shows up as a system tray icon near to the system clock. A few seconds later, this icon disappears, just to show up again after some seconds.

This process repeats over and over again. Tools like usbview or snoopypro seem not to be able to log what's going on during this startup phase, so I'm happy for every hint...

I've ensured that the uC is running with external clock, Zener-diodes have been connected to the D-lines (during startup I have 3,2V at D+ and 0V at D-)

z0ttel

Post by z0ttel » Wed Dec 26, 2007 8:30 pm

When I plug the device to my Linux box, I get following messages:

usb 1-1.1: new low speed USB device using uhci_hcd and address 4
usb 1-1.1: device descriptor read/64, error -71
usb 1-1.1: device descriptor read/64, error -71
usb 1-1.1: new low speed USB device using uhci_hcd and address 5
usb 1-1.1: device descriptor read/64, error -71
usb 1-1.1: device descriptor read/64, error -71
usb 1-1.1: new low speed USB device using uhci_hcd and address ...


Does anybody knows what error -71 means?

z0ttel

Post by z0ttel » Wed Dec 26, 2007 8:54 pm

Ok, I solved this (was a wiring problem :oops: )

Now the device gets recognized as an 'Unknown device', usbview says 'DeviceFailedEnumeration'

Any idea on this?

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Wed Dec 26, 2007 9:03 pm

Hmmm... You should be able to capture a USB snoop this time....

Guest

Post by Guest » Thu Dec 27, 2007 1:16 pm

Hi,

I checked everything again this morning and found another wiring problem. After fixing this, the device gets recognized by windows, but not in the expected way:

    - In the device manager, it's still shown as 'unknown device' in the category 'usb-controller'
    - Sometimes, there's a yellow exclamation mark, sometimes not
    - In all cases, usbview says 'DeviceFailedEnumeration'
    - In all cases, snoopypro isn't able to log any communication with the device
    - Although I enabled the debugging interface (-DDEBUG_LEVEL=2), I get no response from the device => which settings have to be made for Hyperterminal?


I try to get this running on my evaluation board, which means I have lots of wires connected -> is the length of the wires of the D-lines critical (at the moment they are ~10cm long)?

z0ttel

Post by z0ttel » Thu Dec 27, 2007 3:20 pm

Christian,

I've stripped the main routine down so that it only contains the functionality which is needed to establish communication.

In my understanding, the following code should be sufficient to get the device properly recognized by windows:

Code: Select all

int main(void)
{
    wdt_enable(WDTO_2S);
    hardwareInit();
    usbInit();
    sei();
    for(;;){    /* main event loop */
        wdt_reset();
        usbPoll();
    }
    return 0;
}


The device still gets detected as 'unknown device' :(


As I already wrote, I'm using the Atmega32 instead of Atmega8 - all I did change was the makefile (MCU=atmega8 to MCU=atmega32).

Because D- is connected to PD0 (pin 14) and D+ is connected to PD2 (pin 16) I didn't have to change anything in usbconfig.h -- is that right?

Are there any other places where the microcontroller is considered?

Are there any other methods how to verify that the usb-stack works fine?


I know, these are many annoying questions, but I want to get this thing running. Other users don't seem to run into those problems so I assume that I'm doing something very wrong

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Thu Dec 27, 2007 8:38 pm

If the device fails enumeration, USB does not work (probably not at all). You get a "not recognized" even if you only connect the 1.5k pull-up resistor.

The ATMega32 should work without any changes, at least at the first glance. I have never used this chip myself, though. It definitely needs other fuse values than the ATMega8. What fuse values do you use?

If you don't see any debug output when debugging is enabled, the bit rate may be wrong. This would be a strong hint that you run the MCU from the internal RC oscillator instead of the crystal.

z0ttel
Posts: 11
Joined: Thu Dec 27, 2007 3:21 pm

Post by z0ttel » Fri Dec 28, 2007 12:20 pm

The ATMega32 should work without any changes, at least at the first glance. I have never used this chip myself, though. It definitely needs other fuse values than the ATMega8. What fuse values do you use?

The lfuse is programmed to 0x9F, the hfuse to 0x09 -- these are the same settings as on the atmega8, the only difference is that the jtag-interface of the atmega32 is enabled (JTAGEN=0, OCDEN=0).
I compared the suggestions in the makefile with the settings I made to the atmega32 with the help of the 'AVR Fuse Calculator' (http://palmavr.sourceforge.net/cgi-bin/fc.cgi?P_PREV=ATmega32) just to prevent errors from wrong fuses.


If you don't see any debug output when debugging is enabled, the bit rate may be wrong. This would be a strong hint that you run the MCU from the internal RC oscillator instead of the crystal.

I've ensured that the micro is running on crystal clock the following way: I toggle a LED if timer1 overflows. timer1 is configured in that way, that the LED should toggle with a period of 1s (extClk=12MHz, prescaler=256 countvalue=46875 ==> period=1s) -- this works.
If the system would run on internal oscillator (1MHz) the LED would toggle about every 12s.

I know, this isn't a very exact method, but it's sufficient to prove the micro is running with the right clock.

Anyway, what are the settings I have to make in Hyperterminal to see any messages from the device (Baudrate, Datab bits, Parity, Stopp bits, Flow control)?

Regards,
Oliver

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Fri Dec 28, 2007 3:40 pm

OK, so let's assume that the fuse values are correct.

The debug output is at 19200 bps by default. Since only the TxD pin is used, there is no flow control. I don't know what settings you need for Hyperterminal, though, if you just want to receive data. If you interface to a PC, you need an inverter (and in principle you need a level converter) because RS232 operates with inverted +/- 12 V levels.

If you add

DBG1(0x00, 0, 0);

to your main() after odDebugInit(), you should at least see this "00" output after startup. Otherwise the driver should print USB Reset ("ff") and received and transmitted packets.

z0ttel
Posts: 11
Joined: Thu Dec 27, 2007 3:21 pm

Post by z0ttel » Fri Dec 28, 2007 7:54 pm

Finaly I was able to log some data via uart: after plug-in of the device, I receive 1 time "00" (1st message) and 15 times "ff" -- that's all. I guess, this isn't a good sign :?

Next, I will test if port D works as expected on my ATmega32 - maybe the micro itself has some errors....


Anyway, is there any point where I can start to debug the usb-stack? Is there a point which is crucial for establishing a communication via USB? I have plenty of LEDs to connect and a JTAG debugger to dig into the code :D

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Fri Dec 28, 2007 7:58 pm

ff stands for Reset. It is output as long as the reset condition is detected on the USB. This indicates that at least the I/O pins can be read correctly.

Did you check the disassembler output to see whether the interrupt table has been compiled correctly? And did you try a different interrupt?

z0ttel
Posts: 11
Joined: Thu Dec 27, 2007 3:21 pm

Post by z0ttel » Fri Dec 28, 2007 9:56 pm

christian wrote:Did you check the disassembler output to see whether the interrupt table has been compiled correctly?

Can you please give me a hint where I have to look and what it should look like?

christian wrote:And did you try a different interrupt?

I tried INT1 instead of INT0 - I connected D+ to INT1 (pin 17) and made following modifications to the code.

in main.c (hardwareInit()):

Code: Select all

    PORTD = 0xf6;   /* 1111 0110 bin: activate pull-ups except on USB lines */
    DDRD = 0x0b;    /* 0000 1011 bin: all pins input except USB (-> USB reset) */
    j = 0;
    while(--j){     /* USB Reset by device only required on Watchdog Reset */
        i = 0;
        while(--i); /* delay >10ms for USB reset */
    }
    DDRD = 0x02;    /* 0000 0010 bin: remove USB reset condition */


in usbconfig.h:

Code: Select all

#define USB_INTR_CFG_SET        ((1 << ISC10) | (1 << ISC11))
#define USB_INTR_ENABLE_BIT     INT1
#define USB_INTR_PENDING_BIT    INTF1


Now I get absolutely no reaction on the PC if I connect the device to it - is there any other section I have to modify if I want to use INT1?

z0ttel
Posts: 11
Joined: Thu Dec 27, 2007 3:21 pm

Post by z0ttel » Sat Dec 29, 2007 1:19 pm

Here are the latest results (there's still no change :( ):

The interrupttable looks good for INT0 and INT1:

INT0:

Code: Select all

Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 7f 00    jmp   0xfe   ; 0xfe <__ctors_end>
   4:   0c 94 f6 02    jmp   0x5ec   ; 0x5ec <__vector_1>
   8:   0c 94 9c 00    jmp   0x138   ; 0x138 <__bad_interrupt>
   c:   0c 94 9c 00    jmp   0x138   ; 0x138 <__bad_interrupt>   
   ...


INT1:

Code: Select all

Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 7f 00    jmp   0xfe   ; 0xfe <__ctors_end>
   4:   0c 94 9c 00    jmp   0x138   ; 0x138 <__bad_interrupt>
   8:   0c 94 f6 02    jmp   0x5ec   ; 0x5ec <__vector_2>
   c:   0c 94 9c 00    jmp   0x138   ; 0x138 <__bad_interrupt>
   ...



And did you try a different interrupt?

If I'm using INT1 instead of INT0 the device still reacts in the same way. I also tried different configurations (D+ connected to INT0 and nothing else, D+ connected to INT0 and PD2) and different versions of the usb stack (2007/03/29 and 2007/12/01) - nothing helped.

It's interesting to see that if I'm using the old usb-stack, I always get the 'toggling behaviour' I described in my very first topic.


Now I assume that the problem is coupled to my evaluation board: yesterday I found out that INT0 is very sensitive to any changes. It is sufficient enough to touch the isolated wires on the backside of the circuit board with my finger to trigger the interrupt service routine if no pull-up resistor is connected.

I ordered some new parts and I will build another evaluation board with short lines especially dedicated for testing this usb-stuff.


If you have another idea where to look please let me know.


Lastly, I activated some more compiler-warnings and got some interesting response:

Code: Select all

usbdrv/usbdrv.c: In function 'usbSetInterrupt':
usbdrv/usbdrv.c:232: warning: passing argument 2 of 'usbCrc16Append' with different width due to prototype
usbdrv/usbdrv.c:234: warning: passing argument 1 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c:234: warning: passing argument 3 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c: In function 'usbProcessRx':
usbdrv/usbdrv.c:321: warning: passing argument 1 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c:321: warning: passing argument 3 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c: In function 'usbBuildTxBlock':
usbdrv/usbdrv.c:470: warning: passing argument 2 of 'usbRead' with different width due to prototype
usbdrv/usbdrv.c:472: warning: passing argument 2 of 'usbCrc16Append' with different width due to prototype
usbdrv/usbdrv.c:482: warning: passing argument 1 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c:482: warning: passing argument 3 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c: In function 'usbPoll':
usbdrv/usbdrv.c:511: warning: passing argument 2 of 'usbProcessRx' with different width due to prototype
usbdrv/usbdrv.c:537: warning: passing argument 1 of 'odDebug' with different width due to prototype
usbdrv/usbdrv.c:537: warning: passing argument 3 of 'odDebug' with different width due to prototype

usbdrv/oddebug.c: In function 'printHex':
usbdrv/oddebug.c:34: warning: passing argument 1 of 'hexAscii' with different width due to prototype
usbdrv/oddebug.c:34: warning: passing argument 1 of 'uartPutc' with different width due to prototype
usbdrv/oddebug.c:35: warning: passing argument 1 of 'hexAscii' with different width due to prototype
usbdrv/oddebug.c:35: warning: passing argument 1 of 'uartPutc' with different width due to prototype
usbdrv/oddebug.c: In function 'odDebug':
usbdrv/oddebug.c:40: warning: passing argument 1 of 'printHex' with different width due to prototype
usbdrv/oddebug.c:41: warning: passing argument 1 of 'uartPutc' with different width due to prototype
usbdrv/oddebug.c:43: warning: passing argument 1 of 'uartPutc' with different width due to prototype
usbdrv/oddebug.c:44: warning: passing argument 1 of 'printHex' with different width due to prototype
usbdrv/oddebug.c:46: warning: passing argument 1 of 'uartPutc' with different width due to prototype
usbdrv/oddebug.c:47: warning: passing argument 1 of 'uartPutc' with different width due to prototype

main.c: In function 'usbFunctionSetup':
main.c:240: warning: passing argument 1 of 'buildReport' with different width due to prototype
main.c: In function 'main':
main.c:268: warning: passing argument 1 of 'odDebug' with different width due to prototype
main.c:268: warning: passing argument 3 of 'odDebug' with different width due to prototype
main.c:294: warning: passing argument 1 of 'buildReport' with different width due to prototype
main.c:295: warning: passing argument 2 of 'usbSetInterrupt' with different width due to prototype


I'm concerned about the warning "passing argument x of 'XYZ' with different width due to prototype" -> I didn't investigate this further but from my experience this point will create problems sooner or later; what do you think about it?

Oh, one last point: which version of winAVR are you using? Maybe this is the reason for all my problems.
I'm currently using winAVR build 20070525


Thanks for your help so far -- have a nice weekend and a happy new year!

Regards,
Oliver

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Sat Dec 29, 2007 6:04 pm

I'm beginning to mix up threads. My reply should have gone to another thread where USB works when connected to INT0 but not with any other interrupt.

If I remember correctly, it does not work regardless of the interrupt in your case.

If the interrupt pin is "open", then it's normal that it is very sensitive to touching or other changes. But it should be connected to D+ anyway.

The warnings are OK. This means that the data type had to be converted for a function call. I'm NOT using WinAVR because I have a Mac, but I know that the driver can be compiled with WinAVR 20070525.

Let's concentrate on the debug output. You get the startup message and you see USB Reset, but you don't get any data. This can be because the interrupt never occurs or because the data is identified as garbage by the interrupt handler.

You should be able to verify whether the interrupt occurs by toggling a LED in the interrupt service routine (temporarily use your own interrupt handler for that). If it does occur and the handler thinks the data is garbage, things become harder to debug. You could toggle LEDs in various places in the assembler module, but that's hard if you are not the author of the code.

z0ttel
Posts: 11
Joined: Thu Dec 27, 2007 3:21 pm

Post by z0ttel » Sun Dec 30, 2007 7:27 pm

christian wrote:If I remember correctly, it does not work regardless of the interrupt in your case.

Right :)


christian wrote:Let's concentrate on the debug output. You get the startup message and you see USB Reset, but you don't get any data. This can be because the interrupt never occurs or because the data is identified as garbage by the interrupt handler.

You should be able to verify whether the interrupt occurs by toggling a LED in the interrupt service routine (temporarily use your own interrupt handler for that).

I have done so - the LED toggles several times after the device has been plugged to the USB. This means that the ISR is triggered as excepted and - following your explanation - the incoming data is garbled or corrupted. Do you have any references (screenshot from oscilloscope) of how the D+ and D- line should look like?


christian wrote:If it does occur and the handler thinks the data is garbage, things become harder to debug. You could toggle LEDs in various places in the assembler module, but that's hard if you are not the author of the code.

Ok, any ideas? :?

Post Reply