Operation with OHCI vs. UCHI host controllers

Question: I have a M8 chip in my device. My device  works fine with UHCI host controller, but it fails with an OHCI host controller.



UHCI host controllers schedule one transfer per 1 ms frame. OHCI host controllers, however, can schedule more than one transfer within a 1ms frame. Due to the locking mechanism on Endpoint 0 Mode and Endpoint 0 Count registers of the M8B microcontrollers, this feature of OHCI turns to be a problem some times.

After receiving a SETUP packet successfully (i.e. sending an ACK to the SETUP), the SIE automatically changes the mode to NAK_IN_OUT and sets the "Endpoint 0 SETUP Received" and the "ACK" bits in the Ep0 Mode register. The EP0 Mode register will be locked until the firmware does a read to the EP0 Mode. While the EP0 Mode register is being locked, the SIE keeps sending NAK to any IN/OUT and sets the EP0 IN Received/EP0 OUT Received bits to "1" if any of these events (IN or OUT) occur.

Normally, after the SIE sends an ACK to the SETUP, the host adds some delay before it sends any IN or OUT. Because the microcontroller runs off a 12MHz clock which is 8 times faster than the low-speed bus (1.5Mb per sec), some low-speed bit time idle is long enough for the microcontroller to read the EP0 Mode register to unlock it, determine what caused the interrupt (a SETUP, IN, or OUT has been received) and branch to an appropriate sub-routine to handle the interrupt.

In the EP0_ISR, after you learn that a SETUP was received, the first thing you should do is to set the mode to NAK_IN_OUT. This is to set the EP0 mode and to clear the rest of the bits in the EP0 Mode register.

It's possible that while you're handling the SETUP interrupt, the host sends an OUT to EP0 (no interrupt will be generated because the EP0 interrupt is disabled). When this happens, the EP0 sends a NAK to the OUT, updates the "EP0 OUT Received" bit, and the EP0 Mode register is locked. Therefore, every time you write to the EP0 Mode, you should read back to see if the register has been locked. If EP0 Mode register has been locked by a new SETUP (EP0 SETUP Received bit set), you should exit the EP0_ISR to service the new SETUP. If EP0 Mode has been locked by an OUT...NAK, you should unlock this register and set the EP0 Mode to the mode you desire.