tinyusb icon indicating copy to clipboard operation
tinyusb copied to clipboard

OHCI usbh, tweaks and improvements

Open Ryzee119 opened this issue 3 years ago • 3 comments

Describe the PR A number of tweaks and improves to the OHCI usb host backend

Additional context

  • Allows configurable root hub ports. I am testing with hardware that has 4 ports. This is working successfully. Fixes for port reset, port speed, port connection status to direct them to the correct rhport.
  • Currently we assume cold boot (OHCI is reset state). This may not be the case if we come from a bootloader etc. This handles SMM mode (Ref OHCI spec 5.1.1.3.3) and Bios mode (Ref OHCI spec 5.1.1.3.4)
  • FrameIntervalToggle must be toggled after we write the FrameInterval (Ref OHCI Spec 7.3.1)
  • We should wait PowerOnToPowerGoodTime after we enable power of the RH ports (Ref OHCI Spec 7.4.1)
  • OHCI will not normally generate port interrupts for devices already connected during init. This will force a reset on the RH on init which seems to reliably trigger connection interrupts on my hardware.
  • There was a bug in ed_list_remove_by_addr that caused some EDs not to be removed on disconnect. This would cause an assert on re-connect as the old ED would continue on. Also set ed->skip to 1, prior to removing it from the queue. OHCI Spec seems to do this (Ref pseudo code in chapter 5.2.7.1.2).
  • Add a small wrapper with weak binding to allow separation of virutal and physical memory for systems that require this. If not required, its just a passthrough that returns the normal address.

Probably will help to review on a per commit basis

Ryzee119 avatar Jun 04 '22 05:06 Ryzee119

superb !! thank you very much for the PR, indeed, I have skipped lots of cpu detail and I think cut lots of corner to just get it running on small MCU. It has been awhile since I work with OHCI, give me a bit of time to revise the spec/code and pull out the old nxp devkit to test with.

hathach avatar Jun 08 '22 10:06 hathach

No rush at all

I will follow up with proper periodic schedule handling (Ohci spec Figure 5-5 tree). I may put this in a #ifdef guard so it can be disabled by the user as it uses a bit of RAM, however this will allows transfers to respect bIntervals and spreads transfers across frames to maximise total available bandwidth.

And I have isochronous support locally, however we need a host isochronous sample to demonstrate :)

Ryzee119 avatar Jun 09 '22 22:06 Ryzee119

Yeah, thanks, I actually build the periodical tree as OHCI specs suggested in early implementation but make it simpler to save footprint. Having it configurable, I think having support 4/8ms (configurable) is better way. Sorry, I am still busy with paid works, will check/test this out whenever I could.

hathach avatar Jun 15 '22 16:06 hathach

@Ryzee119 I've given this PR a go and it's working on my EA4088 board with both OHCI root hub ports which is excellent.

I needed to make some changes for my environment (OPT_OS_NONE, gcc 10.3.1) to fix some compilation issues:

diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c
index 76f97844c..cd747093a 100644
--- a/src/portable/ohci/ohci.c
+++ b/src/portable/ohci/ohci.c
@@ -35,7 +35,11 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
+#if CFG_TUSB_OS == OPT_OS_NONE
+#include "bsp/board.h"
+#else
 #include "osal/osal.h"
+#endif
 
 #include "host/hcd.h"
 #include "ohci.h"
@@ -166,17 +170,27 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr);
 //tuh_get_phys_addr and tuh_get_virt_addr in your application.
 TU_ATTR_WEAK void *tuh_get_phys_addr(void *virtual_address);
 TU_ATTR_WEAK void *tuh_get_virt_addr(void *physical_address);
-TU_ATTR_ALWAYS_INLINE static void *_phys_addr(void *virtual_address)
+TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address)
 {
   if (tuh_get_phys_addr) return tuh_get_phys_addr(virtual_address);
   return virtual_address;
 }
-TU_ATTR_ALWAYS_INLINE static void *_virt_addr(void *physical_address)
+TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address)
 {
   if (tuh_get_virt_addr) return tuh_get_virt_addr(physical_address);
   return physical_address;
 }
 
+static void delay_ms(uint32_t ms)
+{
+#if CFG_TUSB_OS == OPT_OS_NONE
+  int now = board_millis();
+  while (board_millis() - now <= ms) asm("nop");
+#else
+  osal_task_delay(ms);
+#endif
+}
+
 // Initialization according to 5.1.1.4
 bool hcd_init(uint8_t rhport)
 {
@@ -206,7 +220,7 @@ bool hcd_init(uint8_t rhport)
   {
     //Wait 20 ms. (Ref Usb spec 7.1.7.7)
     OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_RESUME;
-    osal_task_delay(20);
+    delay_ms(20);
   }
 
   // reset controller
@@ -233,7 +247,7 @@ bool hcd_init(uint8_t rhport)
 
   OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // make HC's state to operational state TODO use this to suspend (save power)
   OHCI_REG->rh_status_bit.local_power_status_change = 1; // set global power for ports
-  osal_task_delay(OHCI_REG->rh_descriptorA_bit.power_on_to_good_time * 2); // Wait POTG after power up
+  delay_ms(OHCI_REG->rh_descriptorA_bit.power_on_to_good_time * 2); // Wait POTG after power up
 
   return true;
 }
@@ -612,7 +626,10 @@ static void done_queue_isr(uint8_t hostid)
   {
     // TODO check if td_head is iso td
     //------------- Non ISO transfer -------------//
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wcast-align"
     ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head;
+    #pragma GCC diagnostic pop
     xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS :
                                 (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED;

wooyay avatar Feb 19 '23 17:02 wooyay

@wooyay thanks for pointed out the issue with osal_task_delay(), though board_millis() cannot be used, since it is application function. We will do it better with additional API later on.

hathach avatar Feb 22 '23 15:02 hathach