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

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Fri Feb 08, 2008 8:26 am
			
			
			
			
			Hello,
I have AVRUSB running on ATTINY45 with RC oscillator on 16.5MHz. I have coded such that I can reset the device via Watchdog timer like this:
Code: Select all
USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
...
   if(rq->bRequest == 0xf){             // Reset by Watchdog
        for (;;){};
        return 0;
    }
When I invoke the watchdog the device will fail to enumerate again. 
Here's my main code:
Code: Select all
int main(void)
{
    OSCCAL=0x5b;
    DDRB = (1 << USB_CFG_DMINUS_BIT) | (1 << USB_CFG_DPLUS_BIT);
    PORTB = 0;             // indicate USB disconnect to host */
    delay(1400000);         // delay 6x1.4=8.4 million clocks = 0.51secs
    DDRB = 0;            //all inputs
    wdt_enable(WDTO_15MS);
    usbInit();
    sei();
    for(;;){    /* main event loop */
           wdt_reset();
           usbPoll();
    }
} 
 
The OSCCAL value is experimentally determined and optimum.
What am I doing wrong?
BTW: Basically the same code on an ATMEGA8 with 12MHz reenumerates fine after watchdog reset.
BR Tom
Regards, Tom
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								christian							 
						- Objective Development

 			
		- Posts: 1443
 		- Joined: Thu Nov 09, 2006 11:46 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by christian » Fri Feb 08, 2008 5:07 pm
			
			
			
			
			You force a RESET in the middle of a USB command. This may confuse the host. It would be cleaner to set a global variable so that the main loop does not call wdt_reset(), but still calls usbPoll() until the reset occurs.
Other than that: Did you check whether delay(1400000) really generates a long enough (> 250 ms) delay? There might be an integer overflow.
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								iphi							 
						- Rank 2

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Fri Feb 08, 2008 7:42 pm
			
			
			
			
			You force a RESET in the middle of a USB command. This may confuse the host. It would be cleaner to set a global variable so that the main loop does not call wdt_reset(), but still calls usbPoll() until the reset occurs. 
Good point. But why is it working every time without fault on a crystal driven atmega8 then? I'll give it a try.
Other than that: Did you check whether delay(1400000) really generates a long enough (> 250 ms) delay? There might be an integer overflow.
I use long integer here which doesn't overflow. Also identical code which works on the atmega8/12MHz.
Could there be something connected to the RC oscillator or the 16.5MHz driver?
Best regards, Tom
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								christian							 
						- Objective Development

 			
		- Posts: 1443
 		- Joined: Thu Nov 09, 2006 11:46 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by christian » Fri Feb 08, 2008 7:46 pm
			
			
			
			
			Just because it works with 12 MHz does not mean that the code does what it's intended to do. Many problems depend on tiny deviations in the timing.
BTW: 1400000 is an integer constant, it would be 1400000L otherwise. Do you get a compiler warning for this?
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								iphi							 
						- Rank 2

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Fri Feb 08, 2008 8:40 pm
			
			
			
			
			BTW: 1400000 is an integer constant, it would be 1400000L otherwise. Do you get a compiler warning for this?
No, there's no compiler warning. As I'm a C beginner I'm quite paranoic to avoid any compiler warnings as I have learned that C warnings are serious in contrast to Pascal warnings. My code compiles with zero errors and zero warnings. I have also checked functionality of the delay loop inside the AVR Studio simulator in sourcecode and in disassembler. All is definitely fine here.
Regards, Tom
P.S. Think I have a hint: I have connected an oscilloscope to one of the USB data lines. I do see the 0.5 second pulse at first connection. But when I invoke the watchdog I do see many and more short pulses but no 0.5 second pulse. Now I just have to think about how to explain this.
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								iphi							 
						- Rank 2

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Fri Feb 08, 2008 11:40 pm
			
			
			
			
			Hi Christian,
my confusion is growing. I have made the following experiments:
1. Done the modification you suggested with the global variable and suppressing the wdtreset in the main loop.
=> doesn't work, same as my first attempt
2. Tried a hardware reset on pin 1 instead:
a) An initial hardware reset works fine, also repeatedly.
b) A hardware reset after the above software reset doesn't bring the device back to life. It continues sending strange signals out the USB bus.
I thought there's nothing higher priority than a hardware reset!???
Do you have any more ideas?
Regards Tom
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								Grendel							 
						- Rank 4

 			
		- Posts: 167
 		- Joined: Sat Dec 16, 2006 9:53 pm
 		
		
																- Location: Oregon, USA
 
							
							- 
				Contact:
				
			
 
				
		
		
						
						
													
							
						
									
						Post
					
								by Grendel » Sat Feb 09, 2008 9:26 am
			
			
			
			
			How is that delay() function defined ?
Do you  have a "dynamic" speed R that allows you to use usbDeviceConnect() and usbDeviceDisconnect() ? I use the same logic to reset my converter but w/ a usbDeviceDisconnect() just before the forever loop. Works every time 

 Plus, you don't need to create a reset condition on the bus after a usbDeviceConnect():
Code: Select all
    wdt_enable( WDTO_500MS ) ;                  // Unleash watchdog
    sei() ;                                     // Enable interrupts
                                                // Preset report
    usbSetInterrupt( sw_report, SW_REPORTSZ ) ;
    usbDeviceConnect() ;                        // Activate ID resistor
    for ( ;; )                                  // Forever..
    {
        wdt_reset() ;                           // Calm watchdog
        usbPoll() ;                             // Do USB stuff
 
No problems whatsoever.
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								iphi							 
						- Rank 2

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Sat Feb 09, 2008 7:10 pm
			
			
			
			
			Hi Grendel,
thanks for your proposal. I'll try that.
All,
I think I have found the reason for the strange behavior of my ATTINY45 compared to the ATMEGA8:
The watchdog remains on even after watchdog reset, thus the system won't stay in the 0.5 second delay loop. This is described in the AVR-libc documentation:
Note that for newer devices (ATmega88 and newer, effectively any AVR that has the option to also generate interrupts), the watchdog timer remains active even after a system reset (except a power-on condition), using the fastest prescaler value (approximately 15 ms). It is therefore required to turn off the watchdog early during program startup, the datasheet recommends a sequence like the following:...
Regards, Tom
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								iphi							 
						- Rank 2

 			
		- Posts: 68
 		- Joined: Mon Jun 25, 2007 11:37 am
 		
		
						
						
		
		
						
						
													
							
						
									
						Post
					
								by iphi » Sat Feb 09, 2008 10:01 pm
			
			
			
			
			I can fonfirm that the above was the reason for my watchdog problems.
After having added the following piece of code suggested in AVR-libc my watchdog reset works perfectly.
 
Code: Select all
#include <stdint.h>
    #include <avr/wdt.h>
    uint8_t mcusr_mirror _attribute_ ((section (".noinit")));
    void get_mcusr(void) \
      __attribute__((naked)) \
      __attribute__((section(".init3")));
    void get_mcusr(void)
    {
      mcusr_mirror = MCUSR;
      MCUSR = 0;
      wdt_disable();
    }
 
Regards, Tom
 
			
			
									
									
						 
		 
				
		
		 
	 
	
				
		
		
			- 
				
																			
								Grendel							 
						- Rank 4

 			
		- Posts: 167
 		- Joined: Sat Dec 16, 2006 9:53 pm
 		
		
																- Location: Oregon, USA
 
							
							- 
				Contact:
				
			
 
				
		
		
						
						
													
							
						
									
						Post
					
								by Grendel » Mon Feb 18, 2008 4:00 am
			
			
			
			
			Funny, I just ran into the same thing after I switched from a mega8 to a tiny461 
