working nicely on my laptop, but fail on my PC?

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

working nicely on my laptop, but fail on my PC?

Post by SimonQian » Fri Apr 11, 2008 1:12 am

recognized by both, but sometimes fails on PC.
Using Bulk.
any possible reason?
or any thing else I can check?

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Fri Apr 11, 2008 12:37 pm

It's really hard to debug cause I have no USB proto analyzer, but I still tried to fight out.
There are 2 kinds of errors.
1.is solved
2 is that Bulk package error, for example, the package format is:
//dat[idx] para(value) --Description
//dat[0] Command
//dat[1] NumBytes(MSB) --Total number of bytes to program(MSB)
//dat[2] NumBytes(LSB) --Total number of bytes to program(LSB)
//dat[3] mode --Mode byte
//dat[4] delay --Delay used for different types of programming termination,according to mode byte
//dat[5] cmd1 --Comamnd byte for Load Page
//dat[6] cmd2 --Command byte for Write Memory
//dat[7] cmd3 --Command byte for Read Memory
//dat[8] poll1
//dat[9] poll2
//data[10] Data --Data to program
........// other data, length of which is define in NumBytes section.

when OK, package length is NumBytes + 10, but when fails, it's larger.
If Data section is read by "dat[10 + i ]" for example, it will fail when package size is error, but succeed if read data by "dat[len - NumBytes + i]", in which "len" is the size of the whole package received, even if package size is error.
Last edited by SimonQian on Sat Apr 12, 2008 3:00 pm, edited 1 time in total.

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Fri Apr 11, 2008 3:30 pm

To find what's wrong, I add these code:
if((10 + NumBytes) < len) {
for(i = 0;i < len;i++)
EEPROM_Write(0x10+i,dat[i]);
}

And found that if error occurs, the first or second 8 bytes is received twice, so the real package size is 18 + NumBytes, and data can be obtained if count from bottom.

I tried 100 times to retrieve data from bottom, and even if the package size is wrong, data retrieved is OK. Another 100 times, I retrieve data from dat[10 + i], and got 9 errors in all.

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

Post by christian » Sat Apr 12, 2008 9:06 pm

This probably means that Sharity was not fast enough sending an ACK so that the host did a USB retry after some time.

What clock frequency do you use? Can you reproduce this? If yes, do you have a digital storage scope to analyze it? Would be really interesting to find out why this happens since bulk endpoints cause problems on some computers.

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Sun Apr 13, 2008 7:39 am

christian wrote:This probably means that Sharity was not fast enough sending an ACK so that the host did a USB retry after some time.

What clock frequency do you use? Can you reproduce this? If yes, do you have a digital storage scope to analyze it? Would be really interesting to find out why this happens since bulk endpoints cause problems on some computers.


It's running on 12MHz.
I CAN reproduce it.
My scope can't store so many data(maybe 1 error among hundreds of packages). I think a USB proto analyzer will do, but I don't have one.
If using a older version, it's not that bad. But still will error occasionally.

Anything else I can do to find the reason?
Try a faster oscillator, and see whether it fails again?
-- tried and failed for same error with 16MHz oscillator.

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

Post by christian » Sun Apr 13, 2008 12:27 pm

The 16 MHz version meets the specs reliably when you use bulk endpoints, the 12 MHz version is very close to the limit.

Since one 8 byte chunk is duplicated, it's almost certain that this is a retry from the host. In principle, it's possible to filter out retries by checking data toggling. But I'd rather try to find out why there is a retry at all.

How much memory do you have in your scope? If you generate a trigger when you receive the duplicate package, would the memory suffice?

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Sun Apr 13, 2008 2:15 pm

I'll try sometime next week.

BTW:
I tried to check the data toggle by this:
in usbdrvasm.S add(myTok is define uchar in main.c):
extern myTok
in asmcommon.S function handleData insert first:
sts myTok,token; this will store token(DATA0 or DATA1) to myTok

This will add 2 cycle delay.
But if I check the data toggle in usbFunctionWriteOut function,
some other package will fails.
I will chech it later if I have time next week.

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

Post by christian » Sun Apr 13, 2008 3:27 pm

You must reset data toggling after each new connection. Do you lose the first chunk or one in the middle?

When you generate a trigger in usbFunctionWriteOut() if data toggling is wrong, you should see many DATA packets which are answered with a NAK between the two with the same token. The main loop code should be as fast as possible to limit this number.

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Wed Apr 16, 2008 3:57 pm

too busssssssssy these days.
Is there any list to show which PC or chipset is more likely to fail with Bulk Transfer?

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

Post by christian » Wed Apr 16, 2008 4:02 pm

I think Osamu has some statistics included with his AVR-CDC project.

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Thu Apr 17, 2008 11:46 am

I add code to check data toggle like this(AVRUSB run at 16M):

Code: Select all

/// Token recorded when receive DATA package
uchar lastTok;

///
/// @brief   AVRUSB will call this function when DATA package is received
/// @param   data   received data to process
/// @param   len      received data length
///
void usbFunctionWriteOut(uchar *data, uchar len)
{
#if 1
   static uchar preTok;

   // not first package, same tok as last package, then ignore
   if(CMD_Len_tmp && (preTok == lastTok))
   {
      uint8 i;
      EEPROM_Write(0x01,preTok);
      EEPROM_Write(0x02,lastTok);
      for(i = 0;i < CMD_Len_tmp;i++)
         EEPROM_Write(0x10 + i,AVR_Device_DataBuff[i]);
      for(i = 0;i < len;i++)
         EEPROM_Write(0x80 + i,data[i]);

      return;
   }
   preTok = lastTok;
#endif
......
}


On my Lenovo T60, it works fine under windows and linux.
On my IBM i Series, it works fine also under windows(have no linux installed)
On my PC(SL-K8AV-R), fials frequently under windows(in fact, never succeed), OK under Linux.
Checking the EEPROM, data token and some data are error.

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

Post by christian » Thu Apr 17, 2008 12:30 pm

Can you please post (or mail me) the EEPROM content (previous and current package) and add a note where see an error?

Another question: Do you use other interrupts than the USB interrupt or do you disable interrupts in your main code?

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Fri Apr 18, 2008 2:10 pm

Code for usbFunctionWriteOut:

Code: Select all

/// Token recorded when receive DATA package
uchar lastTok;

///
/// @brief   AVRUSB will call this function when DATA package is received
/// @param   data   received data to process
/// @param   len      received data length
///
void usbFunctionWriteOut(uchar *data, uchar len)
{
#if 1
   static uchar preTok;

   // not first package, same tok as last package, then ignore
   if(CMD_Len_tmp && (preTok == lastTok))
   {
      uint8 i;
      EEPROM_Write(0x01,preTok);
      EEPROM_Write(0x02,lastTok);
      EEPROM_Write(0x03,CMD_Len_tmp);
      EEPROM_Write(0x04,len);
      for(i = 0;i < CMD_Len_tmp;i++)
         EEPROM_Write(0x10 + i,AVR_Device_DataBuff[i]);
      for(i = 0;i < len;i++)
         EEPROM_Write(0x80 + i,data[i]);

      LED_On(LED_Green);
      while(1);

      return;
   }
   preTok = lastTok;
#endif

   memcpy(AVR_Device_DataBuff + CMD_Len_tmp,data,len);
   CMD_Len_tmp += len;

......
}


PC should send(12 bytes in Hex): 10 C8 64 19 20 00 53 03 AC 53 00 00
EEPROM content(in Hex) On error(addr:data):
1.
0x01:C3
0x02:C3
0c03:08
0c04:04
0x10:10 C8 64 19 20 00 53 03
0x80:AC 53 00 00
Error: same DATA PID
2.
0x01:4B
0x02:4B
0c03:08
0c04:04
0x10:10 C8 64 19 20 00 53 03
0x80:AC 53 00 00
Error:same DATA PID

Tried 50 times,
Running on my PC under Linux, the green LED is never on.
Running on my PC under Windows, can't pass even once.

Bad driver for Windows? But it drives my USB mice and keyboard well.

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

Post by christian » Fri Apr 18, 2008 3:27 pm

Where exactly do you store lastTok in the assembler code? Do you store it even if the request is answered with NAK? This would explain it: Data is only stored if we answer with ACK, but lastTok may change if a packet has been rejected meanwhile.

SimonQian
Posts: 19
Joined: Fri Nov 30, 2007 6:42 am

Post by SimonQian » Sat Apr 19, 2008 7:45 am

It's OK after I only store the DATA token when ACK is sent:

Code: Select all

handleData:
mov x3, token
    lds     token, usbCurrentTok;[18]
    tst     token               ;[20]
    breq    doReturn            ;[21]
    lds     x2, usbRxLen        ;[22]
    tst     x2                  ;[24]
    brne    sendNakAndReti      ;[25]
; 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              ;[26] zero sized data packets are status phase only -- ignore and ack
    brmi    sendAckAndReti      ;[27] keep rx buffer clean -- we must not NAK next SETUP
sts lastTok, x3
    sts     usbRxLen, cnt       ;[28] store received data, swap buffers
    sts     usbRxToken, token   ;[30]
    lds     x2, usbInputBufOffset;[32] swap buffers
    ldi     cnt, USB_BUFSIZE    ;[34]
    sub     cnt, x2             ;[35]
    sts     usbInputBufOffset, cnt;[36] buffers now swapped
    rjmp    sendAckAndReti      ;[38] 40 + 17 = 57 until SOP


Checking the EEPROM, some package is really sent twice, and even there is a data error among them.
Just ignore the resent package, it's running well. Tested many times, never fails.

Post Reply