USB connection stuck in usb_host_start_transaction

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB connection stuck in usb_host_start_transaction

2,208 Views
Frelon
Contributor I

I use the CMX routines downloaded from Freescale Web Site, a MCF52211 and CodeWarrior 7.0. I have 2 important issues related to the usb_host_start_transaction() function:

1- There is a USB key that can not be read/write or initialized at all. It is a standard USB key (1GB) and it is working correctly on my PC (Windows XP);

2- During a transfer (read or write), when I remove a USB key, any key, the action is well supported most of the time, but some time not (1/20 with some keys, problematic each time for few keys);

 

The common thing with these 2 problems is that the ColdFire is waiting infinitely in the following loop of usb_host_start_transaction() :

while((MCF_USB_INT_STAT & (MCF_USB_INT_STAT_TOK_DNE | MCF_USB_INT_STAT_STALL | MCF_USB_INT_STAT_ERROR)) ==0)

{

   if (MCF_USB_INT_STAT & MCF_USB_INT_STAT_USB_RST)

   {

        evt_disconnect();

        tr_error=tre_disconnected;

        return((hcc_u16)-1u);

   }

}

 

I tried to resolve the problem by checking the following post:

http://forums.freescale.com/freescale/board/message?board.id=CFCOMM&message.id=4944&query.id=100893#...

and

http://forums.freescale.com/freescale/board/message?board.id=CFCOMM&message.id=5182&query.id=100901#...

but without success.

 

Note: for point #1, I also tried the same USB key on a M52210DEMO board with original Freescale code on it to make sure it was not specific to my software project, but the same problem happen. It freezes after "Mass-storage driver started”.

 

Did someone got that problem too and overcome it?
 
Frelon
Labels (1)
0 Kudos
Reply
4 Replies

751 Views
RichTestardi
Senior Contributor II
My experience has been that when you get "stuck" waiting for TOK_DNE, you're not actually stuck at all, but in an infinite (hardware) retry loop where the device is returning infinite NAKs.  If you turn of hardware retries (RETRY_DIS = 1) then you might be able to see the NAKs (you'll get a TOK_DNE for each) to confirm it...  Or if you put on a USB analyzer, that's even easier yet!
 
What I found was that many keys depend on a very specific (certainly against the spirit of the SBC standard) order of commands during initialization, including magic sequences of Inquiry, Test Unit Ready, Request Sense, and Read Capacity.  Apparently they all expect the order that Windows happens to send, and if you do a different order, things get confused.
 
We eventually got every key we had (about 20-30, including card readers and multi-LUN devices, not to mention a half dozen MST-capable cameras) working with our initialization sequence, which is below if it helps.  The API is for our custom USB host/device driver (source available in skeleton.zip at http://www.cpustick.com/downloads.htm), but I believe the command sequence should be obvious from it if you want to try and mimic it.  (I definitely found keys CMX could not talk to for this reason, when attempting to isolate the bugs and going back and forth between drivers.)
 
Code:
        // set interface        usb_setup(0, SETUP_TYPE_STANDARD, SETUP_RECIP_INTERFACE, 0x0b, 0, 0, 0, &setup);        rv = usb_control_transfer(&setup, NULL, 0);        //assert(rv == 0);        // get max lun        usb_setup(1, SETUP_TYPE_CLASS, SETUP_RECIP_INTERFACE, 0xfe, 0, 0, sizeof(max_lun), &setup);        max_rv = usb_control_transfer(&setup, &max_lun, sizeof(max_lun));        //assert(max_rv == 1 && max == 0);                scsi_lun = 0;XXX_NEXTLUN_XXX:                // inquiry        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x12;  // inquiry        cdb[4] = 36;        rv = scsi_bulk_transfer(1, cdb, 6, buf, 36);        if (rv < 0) {            return rv;        }        assert(rv == 36);                // test unit ready        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x00;  // test unit ready        rv = scsi_bulk_transfer(0, cdb, 6, NULL, 0);                // request sense        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x03;  // request sense        cdb[4] = 18;        rv = scsi_bulk_transfer(1, cdb, 6, buf, 18);        if (rv < 0) {            return rv;        }        assert(rv);                // test unit ready        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x00;  // test unit ready        rv = scsi_bulk_transfer(0, cdb, 6, NULL, 0);        if (rv < 0 && max_rv == 1 && scsi_lun < max_lun) {            scsi_lun++;            goto XXX_NEXTLUN_XXX;        }        if (rv < 0) {            return rv;        }                    // read format capacities        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x23;  // read format capacities        cdb[8] = sizeof(buf);        rv = scsi_bulk_transfer(1, cdb, 12, buf, sizeof(buf));        assert(rv);                // read capacity        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x25;  // read capacity        rv = scsi_bulk_transfer(1, cdb, 10, buf, 8);        assert(rv == 8);                // request sense        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x03;  // request sense        cdb[4] = 18;        rv = scsi_bulk_transfer(1, cdb, 6, buf, 18);        assert(rv);        // test unit ready        memset(cdb, 0, sizeof(cdb));        cdb[0] = 0x00;  // test unit ready        rv = scsi_bulk_transfer(0, cdb, 6, NULL, 0);

 
0 Kudos
Reply

751 Views
Frelon
Contributor I
Hi Rich, thank you for your answer, it gives us new ideas of sequence to use to be more compatible. Also I will check if there is some information about the order that Windows sends these commands.
 
Frelon
0 Kudos
Reply

751 Views
DMV
Contributor I
 
Simple Change:
 
From
'static void demo_process(void)
...
    if (tr_error != tre_none) demo_info.state=DMST_BADDEV;
..."
 
To
 
'static void demo_process(void)
...
      if (tr_error != tre_none)
      {
          //Reset Device
          demo_info.nlun = DMST_NODEV;
          demo_info.state =DMST_NODEV;
          //Reset USB
          host_init();
          scsi_init();
      }
..."
 
 
Background:
------------------
Expanded error reporting of  "if (tr_error != tre_none) " to report all errors
 
/* Error codes. */
typedef enum {
  tre_none=0,
  tre_not_running,  /* host operation disabled */
  tre_no_device,    /* no device connected */
  tre_disconnected, /* device has been disconnected */
  tre_stall,        /* endpoint halted by device*/
  tre_data_error,   /* communicatin error (CRC, etc...)*/
  tre_silent,       /* device returned no handshake at all */
  tre_no_ep         /* endpoint not configured */
} tr_error_t;
 
Found CMX errors and lockups when
 1). With flash drive repeat wiggle/ removal / re insert, causes  tre_data_error "Communication error (CRC, etc...)" then gets stuck in while(MCF_USB_CTL & MCF_USB_CTL_TXDSUSPEND_TOKBUSY) (DemoJM & Custom PCB)
 2). No Drive, using internal regulator (touch usb connector  D+/D- Lines) causes  tre_data_error "Communication error (CRC, etc...)" then gets stuck in long stack_size(byte pattern) (Custom PCB)
  
David
Perth, Australia
0 Kudos
Reply

751 Views
DMV
Contributor I
0 Kudos
Reply