[Request] USB Host Shield 2.0

@peekay123, thanks.

Guys, I have been trying this same porting exercise using @peekay123 code as starting point. I fixed some of the pin issues based on @wesner0019 comments. Everything compiles, however the hardware issues I’m experiencing now are:

(1) Not a clean flash. Logs show ‘spark/flash/status/’ = “failed”. The app does still flash and execute…at least to some degree. But the consistent “failed” status is concerning.

(2) The Usb.Init() and/or Usb.Task() causes the hardware to go into ‘Cloud not connected’ mode after about 30sec. Something is broken here and I can’t root cause it. Code below for the the USB functions in USB.cpp

Any ideas?

BTW: I’m using Sparkfun P1 Photon Redboard: https://learn.sparkfun.com/tutorials/photon-redboard-hookup-guide?_ga=1.106473027.1103565691.1449801131

/* Initialize data structures */
void USB::init() {
        //devConfigIndex = 0;
        bmHubPre = 0;
}

void USB::Task(void) //USB state machine
{
        uint8_t rcode;
        uint8_t tmpdata;
        static unsigned long delay = 0;
        //USB_DEVICE_DESCRIPTOR buf;
        bool lowspeed = false;

    MAX3421E::Task();

    tmpdata = getVbusState();

    /* modify USB task state if Vbus changed */
    switch(tmpdata) {
            case SE1: //illegal state
                    usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
                    lowspeed = false;
                    break;
            case SE0: //disconnected
                    if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
                            usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
                    lowspeed = false;
                    break;
            case LSHOST:

                    lowspeed = true;
                    //intentional fallthrough
            case FSHOST: //attached
                    if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
                            delay = millis() + USB_SETTLE_DELAY;
                            usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
                    }
                    break;
    }// switch( tmpdata

    for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
            if(devConfig[i])
                    rcode = devConfig[i]->Poll();

    switch(usb_task_state) {
            case USB_DETACHED_SUBSTATE_INITIALIZE:
                    init();

                    for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
                            if(devConfig[i])
                                    rcode = devConfig[i]->Release();

                    usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
                    break;
            case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
                    break;
            case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
                    break;
            case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
                    if((long)(millis() - delay) >= 0L)
                            usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
                    else break; // don't fall through
            case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
                    regWr(rHCTL, bmBUSRST); //issue bus reset
                    usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
                    break;
            case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
                    if((regRd(rHCTL) & bmBUSRST) == 0) {
                            tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
                            regWr(rMODE, tmpdata);
                            usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
                            //delay = millis() + 20; //20ms wait after reset per USB spec
                    }
                    break;
            case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
                    if(regRd(rHIRQ) & bmFRAMEIRQ) {
                            //when first SOF received _and_ 20ms has passed we can continue
                            /*
                            if (delay < millis()) //20ms passed
                                    usb_task_state = USB_STATE_CONFIGURING;
                             */
                            usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
                            delay = millis() + 20;
                    }
                    break;
            case USB_ATTACHED_SUBSTATE_WAIT_RESET:
                    if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
                    else break; // don't fall through
            case USB_STATE_CONFIGURING:

                    //Serial.print("\r\nConf.LS: ");
                    //Serial.println(lowspeed, HEX);

                    rcode = Configuring(0, 0, lowspeed);

                    if(rcode) {
                            if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
                                    usb_error = rcode;
                                    usb_task_state = USB_STATE_ERROR;
                            }
                    } else
                            usb_task_state = USB_STATE_RUNNING;
                    break;
            case USB_STATE_RUNNING:
                    break;
            case USB_STATE_ERROR:
                    //MAX3421E::Init();
                    break;
    } // switch( usb_task_state )

}

You’ve got some loops and fn-calls with “unknown” run time, maybe sprinkling in some Particle.process() calls might help the cloud drops.

@henn0124, try this for testing. I’ve basically stripped out all unneeded other files like for the xbox.

Seems to be working fine using the keyboard example.

1 Like

@wesner0019 Thanks. I actually figured it out already, but wish I had your code to reduce the headache. The PLATFORM_ID’s were not declared properly in my code. Hope others find your example useful.

@henn0124, @henn0124, it sounds like I should post the code to github so folks like you can do pull requests! Any thoughts?

1 Like

@peekay123 I was able to use majority of your dropbox code, but suppose github might be a little more convenient for most. I didn’t look through @wesner0019 github repo, but it might be the same result as yours.

1 Like

@henn0124, if I can get a tested working set of files, I’d gladly make a github repo for it!

@peekay123, this code was ported for the core and photon, can it be easily ported for the electron by adding PLATFORM_ID ==10 in the areas that have the below generic definitions? Or would be more involved?

#if (PLATFORM_ID == 0) || (PLATFORM_ID == 6)	// Core or Photon

#endif

Thanks

@wesner0019, yes but since there are extra GPIO pins on the Electron, there is on file I believe that would need to take that into consideration. Otherwise, as is, only the Photon pins are mapped, which the Electron matches.

@peekay123, thanks, so if I don’t need the extra Electron pins I should be good then?

@wesner0019, I believe so.