Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve plugin detection in busprobe() #653

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tmk
Copy link
Contributor

@tmk tmk commented Jul 25, 2021

I like to share this busprobe() patch and need code review and your thought on it.

Seems like MAX3421e CONDETIRQ(Connect/Disconnect Interrupt) doesn't arise for every plugin event and the chip fails to detect it sometimes. (Meanwhile, I never seen the chip failed in detection of unpluging.)

For confirmaion I tried to catch INT pin change and read bus state immedately using ISR(), but it still failed to detect device insertion event occasionally. So I believe that we cannot rely solely on the CONDETIRQ interrupt for plugin detection.

This patch checks bus state at every Task() call when vbusState is SE0(no device) regardless of INT pin.
There are some descriptions of the fix here also. tmk#9

These issues are related probably. #425 #452

MAX3421E CONDETIRQ fails to detect device plugging sometimes,
we have to check bus lines regularly during bus state is SE0
to know device insertion.
#9
if (vbusState != SE0) return;

// read current bus state
regWr(rHCTL, bmSAMPLEBUS);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you wait for the operation to finish like how it is done elsewhere in the code?

I.e:

while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That code seems to use contrary logic according to MAX3421E reference?
From my tests the waiting code does nothing and is not needed in fact.

The chip reference(AN3785.pdf p.52) says:

The CPU sets the SAMPLEBUS bit to instruct the SIE to sample the state of the D+ and D-
lines. The SIE clears the SAMPLEBUS bit when it completes the operation.

But the SAMPLEBUS bit shows strange behaviour there in fact.

I never seen 'S' with code below.

while (!(regRd(rHCTL) & bmSAMPLEBUS)) { Serial.print("S "); };

While this code is repeated forever for some reason.

while (regRd(rHCTL) & bmSAMPLEBUS) { Serial.print("S "); };

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the SAMPLEBUS bit is cleared in between the two calls.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With some more tests the SAMPLEBUS bits doesn't seems to be cleared until bus state is changed but not always. This is clearly not what the reference describes, we can't use the bit to wait for sampling bus state anyway.

And simply asserting SAMPLEBUS everytime before reading J/KSTATUS is good practice seemingly. This is what MaximUSBLab10 code does.

My code works in my tests at least so far.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Let's leave it as is then :)

@Lauszus
Copy link
Collaborator

Lauszus commented Jul 26, 2021

Sounds good to me, as the overhead is minimal.

@@ -553,6 +573,9 @@ uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
// }
// usbSM(); //USB state machine
return ( rcode);
*/
busprobe();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment why the code above was commented out and replaced with just busprobe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this proper for the comment? If so I'll commit it.

// CONDETIRQ can miss detection of plugin and check bus every time anyway #653

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about something like this:

/* MAX3421 state change task and interrupt handler */
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
#if 0
        uint8_t rcode = 0;
        uint8_t pinvalue;
        //USB_HOST_SERIAL.print("Vbus state: ");
        //USB_HOST_SERIAL.println( vbusState, HEX );
        pinvalue = INTR::IsSet(); //Read();
        //pinvalue = digitalRead( MAX_INT );
        if(pinvalue == 0) {
                rcode = IntHandler();
        }
        //    pinvalue = digitalRead( MAX_GPX );
        //    if( pinvalue == LOW ) {
        //        GpxHandler();
        //    }
        //    usbSM();                                //USB state machine
        return ( rcode);
#else
        // Seems like MAX3421e CONDETIRQ (connect/disconnect Interrupt) doesn't arise for every plugin event, 
        // so instead we check the bus state at every call to Task when no device is connected
        // See: https://github.com/felis/USB_Host_Shield_2.0/pull/653
        busprobe();
#endif
        return 0;
}

I think the above code makes it more clear what the old vs new code is as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good!
Please feel free to add it as new commit or change existent commit before merging.

Thanks for your service on this library as always!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants