The code base we are working with has support for the USB controller in host mode. This is what OTG is all about after all -- the controller can act either as a host or as a device. I have no intention of doing anything at this time with host mode. So host code is just more clutter and in the way. I want to move it to its own files which I can ignore and not compile. The use of "ifdef" sections is an attempt to do this, but just yields clutter and confusion.
pdev->cfg.phy_itface &pdev->hw->GREGS->GCCFGWhy not get rid of "hw" and "cfg" and just flatten out the structure? The code would be less verbose, which would be an immediate benefit. Would the compiler be able to generate better code? Probably not, but it is worth investigating.
int pickle ( USB_OTG_CORE_HANDLE *pdev ) { if (pdev->cfg.coreID == 0) return 0; else return 1; }Then I look at the generated ARM assembly (I always generate hydra.dump):
08001e5cThis code is as good as I can hope for (I do compile with -O), the "coreID" element is accessed by the offset #11 relative to the structure pointer in r0. We do see a curious and interesting instruction "it" that I have never encountered before -- and this looks like thumb code with 16 bit instructions, but those topics are aside from the current question. My conclusion is that flattening the structure will not benefit the compiler, but it will benefit us by yielding more concise code.: 8001e5c: 7ac0 ldrb r0, [r0, #11] 8001e5e: 3800 subs r0, #0 8001e60: bf18 it ne 8001e62: 2001 movne r0, #1 8001e64: 4770 bx lr
USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_STS status = USB_OTG_OK; USB_OTG_GAHBCFG_TypeDef ahbcfg; ahbcfg.d32 = 0; ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ USB_OTG_MODIFY_REG32(&pdev->hw->GREGS->GAHBCFG, ahbcfg.d32, 0); return status; }I would certainly rewrite this as follows, getting rid of the "status" variable, and using something simple (like "val") rather than the needless clutter of a name like "ahbcfg". We can do far better (see below).
USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_GAHBCFG_TypeDef val; val.d32 = 0; val.b.glblintrmsk = 1; /* Enable interrupts */ USB_OTG_MODIFY_REG32(&pdev->hw->GREGS->GAHBCFG, val.d32, 0); return USB_OTG_OK }But the resulting code is pretty good:
0800204eAll evidence of the union for GAHBCFG has vanished, and the modify macro has been handled as well as could be imagined. The need to step along from hw to GREGS is due to my own changes where I introduced "hw" as a pointer rather than embedding the structure. I did this in order to avoid having to pull in the entire deviceregs structure which would require code in "library" to include header files in "driver". I may rethink that in some way that avoids (or minimizes) having dependence between "library" and "driver". The idea is that someday we can substitute an entirely different driver without any changes to the library code.: 800204e: 68c3 ldr r3, [r0, #12] ; fetch hw 8002050: 681a ldr r2, [r3, #0] ; fetch GREGS 8002052: 6893 ldr r3, [r2, #8] ; access GAHBCFG 8002054: f023 0301 bic.w r3, r3, #1 8002058: 6093 str r3, [r2, #8] ; access GAHBCFG 800205a: 2000 movs r0, #0 800205c: 4770 bx lr
As a final note, I would probably rewrite this routine as:
static void DisableGlobalInt ( CORE_HANDLE *pdev) { pdev->hw->GREGS->GAHBCFG &= ~GLBLINTRMSK; }
dctl.d32 = USB_OTG_READ_REG32(&pdev->hw->DREGS->DCTL); dctl.b.sftdiscon = 0 USB_OTG_WRITE_REG32(&pdev->hw->DREGS->DCTL, dctl.d32);Here we have the needless "accessor macros" along with overly verbose names for them. I could nicely convert this to one line of C as shown above. The only reason to have accessor macros like this is for architectures (like the x86) where there are explicit ioread and iowrite hardware instructions. At least that was true of the x86 in the very old days. Today even on the x86, most hardware registers are memory mapped and all of this clutter and verbosity is pointless, useless, and stupid.
On the ARM it is even more senseless, silly, and ridiculous.
Tom's Computer Info / tom@mmto.org