Choď na obsah Choď na menu
 

Enumeracia PIC

[pic18F] Send a stall packet - USB ennumeration

Hi everyone, 
  
My device is a pic18f4550 on an easypic 5. 
I would like to send a stall packet to the Host (Windows 7) because I have receive a setup token for "Device Qualifier Descriptor" 

If a full-speed only device receives a GetDescriptor() request for a device_qualifier, it must respond with a request error. Then, the host must not make a request for an other_speed_configuration descriptor
So I have to respond with a request error (I think it is a stall packet... but I am not sure) 
  
Tha last setup transaction is received by the part of my code : 
 
 /**********************/ 
     /* SETUP Token DATA 0 */ 
     /**********************/ 
     BD0_OUT.CNT = 8; // size 
     BD0_OUT.ADRH = 0x05; // adresse of Endpoint 0 descriptor 
     BD0_OUT.ADRL = 0x28;  
     BD0_OUT.STAT = UOWN | DTSEN; // flags 
     while(!UIRbits.TRNIF){} // while transaction is not complete 
     UIRbits.TRNIF = 0; // transaction complete 
     pid = (BD0_OUT.STAT & 0x3C) >> 2; // is it a setup token ? 
     if (pid!=SETUP_TOKEN)printError(38); 
 
  
To reply I use a similar structure : 
 
 /*******************/ 
     /* IN Token DATA 1 */ 
     /*******************/ 
     BD0_IN.CNT  = 0x09; 
     BD0_IN.ADRH = 0x05;  //address 
     BD0_IN.ADRL = 0x42; 
     BD0_IN.STAT = UOWN | DTS | DTSEN; 
 
But I don't know how to send a stall packet to the host (or a request error)... 
  
Sorry, if it is not cleared... 
  
Thanks you :) 
  
 
newfound
Super Member
 
  • Total Posts : 1761
  • Reward points : 0
  • Joined: 11/7/2003
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Sunday, October 28, 2012 9:59 PM (permalink)
 
 
0
The short and sweet answer is that yes a request error means you send a stall in reply and to do this you set the BSTALL bit in BD0_IN.STAT for the STATUS stage reply. 

BD0_IN.STAT = UOWN | DTS | DTSEN | BSTALL;

On a different note, this is unlikely to be correct:
BD0_IN.CNT  = 0x09; 
Should be 0x0 for a STATUS stage reply and not more than 0x08 if you have defined the EP0 endpoint size as 8. However the last bit is just an assumption that you have set EP0 MAXPACKETSIZE to 8. If not disregard the last bit.
 
fdiedler
New Member
 
  • Total Posts : 17
  • Reward points : 0
  • Joined: 10/4/2012
  • Location: 0
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Sunday, October 28, 2012 10:21 PM (permalink)
 
 
0
Hi ! 
   
 I always do it but it does not work :( 
  
 unsigned char UOWN  = 0x80;  
 unsigned char DTS   = 0x40;  
 unsigned char DTSEN = 0x08;  
 unsigned char BSTALL = 0x04;  
    
 /**********************/  
     /* SETUP Token DATA 0 */  
     /**********************/  
     BD0_OUT.CNT = 8;  
     BD0_OUT.ADRH = 0x05;  
     BD0_OUT.ADRL = 0x28;  
     BD0_OUT.STAT = UOWN | DTSEN;  
     while(!UIRbits.TRNIF){}  
     UIRbits.TRNIF = 0;  
     pid = (BD0_OUT.STAT & 0x3C) >> 2;  
     if (pid!=SETUP_TOKEN)printError(38);  
 printDataSetup(9); // SETUP #9 (see screenshot)  
 
     /**********************/  
     /* REPLY WITH STALL   */  
     /**********************/  
     BD0_IN.CNT  = 0x00;  
     BD0_IN.STAT = UOWN | DTS | DTSEN | BSTALL;  
     while(!UIRbits.TRNIF){}  
     lcd_puts("I AM HERE");  
 
I never have "I AM HERE" on my LCD screen. So I'am blocked in the loop   while(!UIRbits.TRNIF){} 
   
 You can see my USB 2.0 ennumeration, I am blocked in the STEP #9 with the SETUP token : 80 06 00 06 00 00 0A 00 
   
  
I have also set bMaxPacketSize of device descriptor to 0x40 (64 bytes). 
  
What is the problem ? I feel hopeless :( 
  
 Thank you :) 
   
 post edited by fdiedler - Sunday, October 28, 2012 10:31 PM
 
newfound
Super Member
 
  • Total Posts : 1761
  • Reward points : 0
  • Joined: 11/7/2003
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Sunday, October 28, 2012 11:54 PM (permalink)
 
 
0
Honestly at this point I would have to advise you to grab one of the numerous USB stacks written for the PIC18 and copy the procedures.There is no shortages of them out there and examples written in C, assy, basic and Jal.
 
A USB stack has to be written to respond to the host in the way the host expects and not what "aught to be happening next."  This means you have to have a RESET handler, chapter9 (Standard requests) handler, an IN handler and a OUT handler for EP0 at a very minimum.  I cannot see these in your code.
 
Doing things like this below, is not something I have ever seen on any working USB stack that I can recall and it is just not a workable way to implement USB.
     while(!UIRbits.TRNIF){}  
     UIRbits.TRNIF = 0;
You need to respond to the host and the host may at anytime decide to issue a bus reset or a new setup packet etc.
 
One very likely reason why your code hangs is because the USB FIFO buffer is full. However it is not possible to tell for certain on the code you have posted. There just is not enough code there to get usb working in any sort of reliable way.
 
 
 
fdiedler
New Member
 
  • Total Posts : 17
  • Reward points : 0
  • Joined: 10/4/2012
  • Location: 0
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 0:25 PM (permalink)
 
 
0
I don't want to use the Microchip USB stack because I do not use C18 compiler but Hi-tech compiler and I want to learn about USB enumeration. 
 I have downloaded the entire Specification of USB 2.0, so I can create a "minimal" stack from scratch for Hi-tech compiler (if you know a code example of a stack for Pic18F and Hi-tech compiler, it would be nice :)) 
   
 You can download all my code here : 
http://www.tutoworld.com/temp/usb_stack.zip 
  
 This code works  because Windows 7 pop-up for a new device :) (but does not find any driver, that is normal, I do not have created it). 
   
 But I am blocked for sending a stall packet to the host, because I do not need to repond to 80 06 00 06 00 00 0A 00 SETUP token... After doing that, the host should sent a SET_CONFIGURATION token and it will be done ! ^^ 
   
 Currently, the code performs these steps : 
 1) SETUP token 8006000100004000 => get device descriptor 
 2) SETUP token 0005020000000000 => set adresse (0x02 in my case) 
 3) Reset on the bus 
 4) SETUP token 8006000100001200 => get device descriptor again 
 5) SETUP token 800600020000FF00 => get configuration descriptor 
 6) SETUP token 8006000200001900 => get all config (endpoints, interfaces, configuration) 
 7) SETUP token 800600030000FF00 => get string descriptor 
 8) SETUP token 800602030904FF00 => get string descriptor with lang ID = English (0x0409) 
9) SETUP token 8006000600000A00 => What is it ?? :( 
  
 I think, I should respond a Stall request... 
   
 Please help me, I am near to goal... 
   
 Thanks a lot :)
 post edited by fdiedler - Monday, October 29, 2012 0:32 PM
 
chinzei
Super Member
 
  • Total Posts : 2249
  • Reward points : 0
  • Joined: 11/7/2003
  • Location: Tokyo, Japan
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 4:31 AM (permalink)
 
 
0
So I'am blocked in the loop   while(!UIRbits.TRNIF){}
Yeah, STALLed transaction doesn't set TRNIF (Transfer completion interrupt), because just a successful transaction raises TRNIF.

I believe your PIC has put STALL handshake to the IN transaction.
And then, the host should put next SETUP, which also recovers error at EP0.
But your firmware doesn't prepare BD0_OUT for this SETUP.
The SETUP (and retries) is not ACKed by the PIC SIE.
At this point, the enumeration goes out of the track.

Before setting STALL to BD0_IN, arm BD0_OUT for the next SETUP.
And then, your firmware may wait for the completion of the next SETUP with "while(!UIRbits.TRNIF){}"
 
I am near to goal...
If your goal would be enumeration just on your Windows version, maybe so.
The enumeration sequence differs, depending on OS and its version.
As newfound said, don't expect "what aught to come next".
Every time when a bus event (like bus reset) or a request comes, process it as defined on the USB spec.

Tsuneo
 
fdiedler
New Member
 
  • Total Posts : 17
  • Reward points : 0
  • Joined: 10/4/2012
  • Location: 0
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 11:10 AM (permalink)
 
 
0
Hi, 
   
chinzei
Before setting STALL to BD0_IN, arm BD0_OUT for the next SETUP. 
 And then, your firmware may wait for the completion of the next SETUP with "while(!UIRbits.TRNIF){}" 
Ahh ok, but still does not work. The code always hangs in the infinite loop while(!UIRbits.TRNIF){} 
   
 Here is my code : 
   
 /**********************/   
     /* GET WEIRD REQUEST 80 06 00 06 ...   
     /**********************/   
     /* SETUP Token DATA 0 */   
     /**********************/   
     BD0_OUT.CNT = 8;   
     BD0_OUT.ADRH = 0x05; // adress of Setup Token   
     BD0_OUT.ADRL = 0x28;   
     BD0_OUT.STAT = UOWN | DTSEN;   
     while(!UIRbits.TRNIF){}  // <---- this loop is OK, I got the setup token :)  
     UIRbits.TRNIF = 0; // transaction complete   
     pid = (BD0_OUT.STAT & 0x3C) >> 2;   
     if (pid!=SETUP_TOKEN)printError(38);   
 printDataSetup(9); // SETUP #9 (see previous screenshot)   
 
     /***********************/   
     /* ARM FROM NEXT SETUP */   
     /***********************/   
     BD0_OUT.CNT = 8;   
     BD0_OUT.STAT = UOWN | DTSEN; // 0x88   
        
     /**********************/   
     /* REPLY WITH STALL   */   
     /**********************/   
     BD0_IN.CNT  = 0x00;   
     BD0_IN.STAT = UOWN | DTS | DTSEN | BSTALL; // 0xCC   
     while(!UIRbits.TRNIF){} // <---------- infinite loop here, the code hangs   
     UIRbits.TRNIF = 0;   
     lcd_puts("I AM HERE");   
 
Is there something wrong ? When UIRbits.STALLIF flag is raised ?
  
chinzeiIf your goal would be enumeration just on your Windows version, maybe so.
You are right, my goal is only to do an enumeration on my version of Windows, just to begin ;) 
 
chinzeiThe enumeration sequence differs, depending on OS and its version. 
 As newfound said, don't expect "what aught to come next". Every time when a bus event (like bus reset) or a request comes, process it as defined on the USB spec.
Yeah, I just want to finish with my "awful" code just for test and then I will try to implement a process for all SETUP request according USB spec. 
   
 Thanks  (and sorry for my bad English)
 post edited by fdiedler - Monday, October 29, 2012 11:13 AM
 
chinzei
Super Member
 
  • Total Posts : 2249
  • Reward points : 0
  • Joined: 11/7/2003
  • Location: Tokyo, Japan
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 2:45 PM (permalink)
 
 
0
When UIRbits.STALLIF flag is raised ?
Didn't you get STALLIF?
Ah, clear UCON.PKTDIS bit, too, before (or after) putting STALL to the IN endpoint.

PKTDIS is set by the USB engine (SIE), when it has received a SETUP transaction.
While PKTDIS is set to '1', all endpoints are NAKing, regardless of its Buffer Descriptor setting. Even BSTALL bit on the BD STAT is ignored.
Firmware is expected to clear PKTDIS, to go ahead.


For the next SETUP transaction, you've set up BD0_OUT.CNT and BD0_OUT.STAT, but leave BD0_OUT.ADRH/ADRL untouched. I remember, the SIE usually increments the BD address registers. Set the BD address registers, too.

Tsuneo
 
fdiedler
New Member
 
  • Total Posts : 17
  • Reward points : 0
  • Joined: 10/4/2012
  • Location: 0
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 4:01 PM (permalink)
 
 
0
Unfortunatly, it still does not work...
I am sorry, I forgot to mention that I have already cleared the UCON.bits.PKTDIS bit in my previous post (I try before and after sending STALL packet, no results).
 
That is weired because I got the STALL flag...
   UCONbits.PKTDIS = 0;
    /***********************/
    /* ARM FROM NEXT SETUP */
    /***********************/
    BD0_OUT.CNT = 8;
    BD0_OUT.ADRH = 0x05; // adress of Setup Token
    BD0_OUT.ADRL = 0x28;
    BD0_OUT.STAT = UOWN | DTSEN; // 0x88
    
    /**********************/
    /* REPLY WITH STALL   */
    /**********************/
    BD0_IN.CNT  = 0x00;
    BD0_IN.STAT = UOWN | DTS | DTSEN | BSTALL; // 0xCC

    // wait for stall condition
    while(!UIRbits.STALLIF){}
    lcd_putch('*'); // <----- it is OK here
    // be ready for next setup transaction
     BD0_OUT.CNT = 8;
    BD0_OUT.ADRH = 0x05; // adress of Setup Token
    BD0_OUT.ADRL = 0x28;
    BD0_OUT.STAT = UOWN | DTSEN;
    UEP0bits.EPSTALL = 0;
    UIRbits.STALLIF = 0;

    while(!UIRbits.TRNIF){} // <------ hangs here...
    UIRbits.TRNIF = 0;
    lcd_puts("I AM HERE");
 
I have seen another code on the Web :
 BD0_OUT.STAT  = 0x80 | 0x04;
BD0_IN.STAT  = 0x80 | 0x04;
 
He sets both EP0 (IN and OUT) with a STALL but still does not work.
 
What is the matter ? :(
 
Thanks
 
chinzei
Super Member
 
  • Total Posts : 2249
  • Reward points : 0
  • Joined: 11/7/2003
  • Location: Tokyo, Japan
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 4:25 PM (permalink)
 
 
0
Maybe, before this code block, your firmware has decoded Get_Descriptor( Device_Qualifier ) request.
 
   UCONbits.PKTDIS = 0;
    /***********************/
    /* ARM FROM NEXT SETUP */
    /***********************/
    BD0_OUT.CNT = 8;
    BD0_OUT.ADRH = 0x05; // adress of Setup Token
    BD0_OUT.ADRL = 0x28;
    BD0_OUT.STAT = UOWN | DTSEN; // 0x88
    
    /**********************/
    /* REPLY WITH STALL   */
    /**********************/
    BD0_IN.CNT  = 0x00;
    BD0_IN.STAT = UOWN | DTS | DTSEN | BSTALL; // 0xCC

    // wait for stall condition
    while(!UIRbits.STALLIF){}
    lcd_putch('*'); // <----- it is OK here
Up to this block, your code seems fine.
But just after this block, your code arms BD0_OUT again.
It doesn't need, as the BD0_OUT has been already armed by above code.
I have suspicion that this extra process would even disturb the SIE to receive SETUP.

Delete this code block, just after above block.
    // be ready for next setup transaction
     BD0_OUT.CNT = 8;
    BD0_OUT.ADRH = 0x05; // adress of Setup Token
    BD0_OUT.ADRL = 0x28;
    BD0_OUT.STAT = UOWN | DTSEN;

Tsuneo
 
fdiedler
New Member
 
  • Total Posts : 17
  • Reward points : 0
  • Joined: 10/4/2012
  • Location: 0
  • Status: offline
Re:[pic18F] Send a stall packet - USB ennumeration Monday, October 29, 2012 6:51 PM (permalink)
 
 
0
Still not... 
Maybe, before this code block, your firmware has decoded Get_Descriptor( Device_Qualifier ) request.
  No, it only get the SETUP Device_Qualifier request with : 
 
 /**********************/ 
     /* GET WEIRD REQUEST 80 06 00 06 ... 
     /**********************/ 
     /* SETUP Token DATA 0 */ 
     /**********************/ 
     BD0_OUT.CNT = 8; 
     BD0_OUT.ADRH = 0x05; // adress of Setup Token 
     BD0_OUT.ADRL = 0x28; 
     BD0_OUT.STAT = UOWN | DTSEN; 
     while(!UIRbits.TRNIF){} 
     UIRbits.TRNIF = 0; // transaction complete 
     pid = (BD0_OUT.STAT & 0x3C) >> 2; 
     if (pid!=SETUP_TOKEN)printError(38); 
 printDataSetup(9); // SETUP #9 (see screenshot) 
 
     UCONbits.PKTDIS = 0; 
 ...... 
 ...... 
 

I try to answer to the Get_Descriptor( Device_Qualifier => 8006000600000A00) SETUP query with a dumb IN packet : 

SETUP #9        8       8006000600000A00 
 IN                   10      0A061001000000080100    2 
But after that, I receive nothing from host... (no next SETUP transaction)
 post edited by fdiedler - Monday, October 29, 2012 6:55 PM