USB module Interrupt Issue

Author
mautry
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2018/05/16 06:59:19
  • Location: 0
  • Status: offline
2018/10/08 08:59:08 (permalink)
0

USB module Interrupt Issue

I am migrating a harmony 1.07 project to 2.06 on a PIC32MZ2048EFG100 based system.  I have managed to get most of it going, but am running into a USB issue.  The general USB interrupt is never firing.  On USB attachment, normally the host sends a reset and I am seeing the RESETIF being set in the USBCSR2 register but the corresponding USBIF in the IEC4 register is never being set despite the USBIE being a 1 and the vector is never called. The offset is correct.   I must be missing something but cannot figure it out.
#1

5 Replies Related Threads

    Paul PortSol
    Super Member
    • Total Posts : 331
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: 0
    • Status: offline
    Re: USB module Interrupt Issue 2018/10/10 05:12:24 (permalink)
    0
    I suggest using the callback feature.
    Interrupts all go to callbacks, which work fine for my USB.
     
    Important lines:
    Callback function:  void vCallback_FilesystemEvent(SYS_FS_EVENT eEvent, void *pEventDataUnused, uintptr_t pContextUnused){...}
     
    In the USB Init:
    vUSB_EnableH(0 , true);//Force Enable Power to USB (If using default USBHSInit then the pointer to this function isn't included)
    SYS_FS_EventHandlerSet(vCallback_FilesystemEvent, (uintptr_t)NULL);// Set the event handler and enable the bus (No Context needed)
    USB_HOST_BusEnable(D_USB_FirstBus);//Note vUSB_EnableH() called above in case default USBHSInit doesn't point to vUSB_EnableH()
     
    ---------
    Some code extracts for my USB Memory stick (Wish this thing kept tabs):
     
    void vCallback_FilesystemEvent(SYS_FS_EVENT eEvent, void *pEventDataUnused, uintptr_t pContextUnused)
    {
    sFiles.uFsCallbacks++;
    switch (eEvent)
    {
    case SYS_FS_EVENT_MOUNT:
    sFiles.bFsConnected = true;
    break;
    case SYS_FS_EVENT_UNMOUNT:
    sFiles.bFsConnected = false;
    sFiles.sLogU.bReady = false;//File not ready for Read
    sFiles.sCfgM.bReady = false;//File not ready for Read
    break;
    case SYS_FS_EVENT_ERROR:
    sFiles.uFsCallbackError++;
    break;
    default:
    sFiles.eFsCallbackUnknown = eEvent;
    sFiles.uFsCallbackUnknown++;
    break;
    }
    }
     
    void vFilesInit( void )// Initialize Log USB Flashdrive
    {
    //SYS_DEBUG_ErrorLevelSet(SYS_ERROR_FATAL);
    //SYS_DEBUG_ErrorLevelSet(SYS_ERROR_DEBUG);
    //SYS_DEBUG_ErrorLevelSet(SYS_ERROR_ERROR);
    vUSB_EnableH(0 /*Port0*/, true);//Force Enable Power to USB (If using default USBHSInit then the pointer to this function isn't included)
    D_PRINTF_Init("Init:USB Power Enabled\n");

    //FileSystem:
    SYS_FS_EventHandlerSet(vCallback_FilesystemEvent, (uintptr_t)NULL);// Set the event handler and enable the bus (No Context needed)
    USB_HOST_BusEnable(D_USB_FirstBus);//Note vUSB_EnableH() called above in case default USBHSInit doesn't point to vUSB_EnableH()
    sFiles.eState = EFSys_InitOnce;
    D_PRINTF_Init("Init:Filesystem = OK\n");

    //LogD: Diagnostic Log
    sFiles.sLogD.eFile = ELogD;
    sFiles.sLogD.eStateW = EFileW_InitOnce; //Initial State
    sFiles.sLogD.cID = 'd';
    sFiles.sLogD.pcName = pcName_LogD; //File's Short Name (for Diag)
    sFiles.sLogD.pcPath = pcPath_LogD; //File's Path
    vRingBufA8_init(&sRingLogD); sFiles.sLogD.psRing = (TRINGBUFA*)&sRingLogD; //Prepare Ring Buffer for Writes
    sFiles.sLogD.uRingIndex=0; //Index for lines written to ring, so can see where any lines missed (i.e. when log removed/forceclosed/etc.)
    sFiles.sLogD.bRingInit = true;
    D_PRINTF_Init("Init:LogD = OK, Buf:%u, Path(%s)\n", uRingBufA8_GetMaxItems(sFiles.sLogD.psRing), sFiles.sLogD.pcPath);

    //LogU: User Log
    sFiles.sLogD.eFile = ELogU;
    sFiles.sLogU.eStateW = EFileW_InitOnce; //Initial State
    sFiles.sLogU.cID = 'u';
    sFiles.sLogU.pcName = pcName_LogU; //File's Short Name (for Diag)
    sFiles.sLogU.pcPath = pcPath_LogU; //File's Path
    vRingBufA8_init(&sRingLogU); sFiles.sLogU.psRing = (TRINGBUFA*)&sRingLogU; //Prepare Ring Buffer for Writes
    sFiles.sLogU.uRingIndex=0; //Index for lines written to ring, so can see where any lines missed (i.e. when log removed/forceclosed/etc.)
    sFiles.sLogU.bRingInit = true;
    D_PRINTF_Init("Init:LogU = OK, Buf:%u, Path(%s)\n", uRingBufA8_GetMaxItems(sFiles.sLogU.psRing), sFiles.sLogU.pcPath);

    //CfgM: Main Configuration File
    sFiles.sCfgM.eFile = ECfgM;
    sFiles.sCfgM.eStateW = EFileW_InitOnce; //Initial State
    sFiles.sCfgM.cID = 'm';
    sFiles.sCfgM.pcName = pcName_CfgM; //File's Short Name (for Diag)
    sFiles.sCfgM.pcPath = pcPath_CfgM; //File's Path
    sFiles.sCfgM.psRing = (TRINGBUFA*)NULL; //No Writes == No Ringbuffer
    sFiles.sCfgM.uRingIndex=-1; //Index for lines written to ring, so can see where any lines missed (i.e. when log removed/forceclosed/etc.)
    sFiles.sCfgM.bRingInit = false;
    D_PRINTF_Init("Init:CfgM = OK, Path(%s)\n", sFiles.sCfgM.pcPath);
    //Cfg Read after USB Mounted
    //Done:
    sFiles.bInit = true;
    }
     
     
    Paul
    #2
    mautry
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/05/16 06:59:19
    • Location: 0
    • Status: offline
    Re: USB module Interrupt Issue 2018/10/11 16:09:08 (permalink)
    0
    OK, if I substitute the following line in the driver code:
        #define _DRV_USBHS_CLOCK_CONTROL_GLOBAL_USB_INT_ENABLE(x) PLIB_USBHS_GlobalInterruptEnable(x)
    with:
        #define _DRV_USBHS_CLOCK_CONTROL_GLOBAL_USB_INT_ENABLE USBCRCONbits.USBIE = 1;
     
    It starts working.  These two are supposed to be the same, right?  The ID is USBHS_ID_0 as expected.
    #3
    Paul PortSol
    Super Member
    • Total Posts : 331
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: 0
    • Status: offline
    Re: USB module Interrupt Issue 2018/10/12 04:08:02 (permalink)
    0
    Right, LOL.
     
    a) Look at the implemented code for PLIB_USBHS_GlobalInterruptEnable(x), and see if it is really what is needed.
    You may have to set a breakpoint in calling function then step into it to see what it does :(
    If not appropriate code then consider posting a ticket so fixed in future and saves others agony.
     
    b) Careful about using PLIB.
    Calling PLIB is kinda like bypassing Harmony, when you do it you become responsible for everything Harmony was supposed to do.
    Macro looks like Harmony Driver is directly using PLIB. 
    In my PIC32MZ that macro is called from within DRV_USBHS_Tasks() called by SYS_Tasks(), I don't directly call it.
    I find SYS_FS_EventHandlerSet() to set callbacks makes the whole interrupt thing easier/cleaner.
    Everyone's preferred style varies.
     
    c) It can help to add counters to USB interrupts so you can see how much they are being called (Periodically display counters in main task or in diagnostic output):
     
    *Only just found out about "code" tags to format code readable (code in square brackets):
    //////////////////////////////////////////////////////////////////////////////////////////////
    // USB = 20180626PR
    // - system_init.c - MHCv2060 - Use the generated drvUSBHSInit, but directly call vUSB_EnableH() before using USB
    //USB: Event Counters for Diag Support
    // - System_interrupt.c
    uint32_t uIntCount_UsbHandler = 0;
    void __ISR( _USB_VECTOR , IPL4AUTO)_IntHandler_USB_stub ( void )
    {
    uIntCount_UsbHandler++;
    if(uIntCount_UsbHandler >=205)
    {
    Nop();// For Breakpoint
    }
    DRV_USBHS_Tasks_ISR(sysObj.drvUSBObject);
    }
    uint32_t uIntCount_UsbHandler0 = 0;
    void __ISR ( _USB_DMA_VECTOR, IPL4AUTO) _IntHandlerUSBInstance0_USBDMA ( void )
    {
    uIntCount_UsbHandler0++;
    DRV_USBHS_Tasks_ISR_USBDMA(sysObj.drvUSBObject);
    }
    //////////////////////////////////////////////////////////////////////////////////////////////
     
    d) Have a look at what Harmony is putting in for "DRV_USBHS_INIT drvUSBHSInit = {...}"
    I've found that it wasn't correctly generated in earlier Harmony Versions for my PIC32MZ, and so I replaced it with my own. Recently it seems better, with the comments below.
    Maybe the interrupt source doesn't match MHC settings? .interruptSource = INT_SOURCE_USB_1
    // Harmony Setup for USB
    // USB = 20180410PR Use the generated drvUSBHSInit, but directly call vUSB_EnableH() before using USB
    //system_init.c == sysObj.drvUSBObject = DRV_USBHS_Initialize (DRV_USBHS_INDEX_0, (SYS_MODULE_INIT *) &drvUSBHSInit);
    //extern DRV_USBHS_INIT drvUSBHSInit;// Required in system_init.c, custom Pins defined in Log_usb_flash.c
    //extern const bool drvUSBHSInit_mod;// "Exists Flag" from system_interrupt.c
    //const _Bool* pSysInt_ADC = &drvUSBHSInit_mod;// Use "Exists Flag" from system_interrupt.c
    //DRV_USBHS_INIT drvUSBHSInit =
    //{
    // .moduleInit = {SYS_MODULE_POWER_RUN_FULL},
    // .interruptSource = INT_SOURCE_USB_1,
    // .interruptSourceUSBDma = INT_SOURCE_USB_1_DMA,
    // .operationMode = DRV_USBHS_OPMODE_HOST,
    // .operationSpeed = USB_SPEED_HIGH,
    // .portIndication = NULL,
    // .portPowerEnable = vUSB_EnableH, //Custom, MHC Generated may place NULL here
    // .portOverCurrentDetect = bUSB_OverCurrentDetect,//Custom, MHC Generated may place NULL here
    // .rootHubAvailableCurrent = 500,
    // .stopInIdle = false,
    // .suspendInSleep = false,
    // .usbID = USBHS_ID_0
    //};

    Good Luck.
    Paul
     
    post edited by Paul PortSol - 2018/10/12 04:15:35
    #4
    Paul PortSol
    Super Member
    • Total Posts : 331
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: 0
    • Status: offline
    Re: USB module Interrupt Issue 2018/10/12 04:12:50 (permalink)
    0
    Also in a fresh project try: MHC -> App Config --> App 0 Config -> Generate App Code
    and select USB features you are interested in to see what is generated, I've found it to be better matched to PIC and Harmony version than any of the pre-generated examples/demonstrations.
    # You can use a tool like "Beyond Compare" to compare MHC generated with and without the "Generate App Code" to see what was added.
    # Don't disable the "Generate App Code" to remove it, it seems to be a one way process (not completely cleanly removed). Instead always start from a fresh new project.
     
    *Don't copy ahead any of the Harmony 1.xx code, best start fresh.
     
    Paul
     
    #5
    mautry
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/05/16 06:59:19
    • Location: 0
    • Status: offline
    Re: USB module Interrupt Issue 2018/10/18 07:05:11 (permalink)
    0
    It appears the issue is in the framework peripheral template files.  The original 1.07 framework gave in usbhs_ClockResetControl_Default.h:
     
    PLIB_TEMPLATE void USBHS_GlobalInterruptEnable_Default( USBHS_MODULE_ID index )
    {
     volatile uint8_t * usbRegMap2BaseAddress = (uint8_t *)_USBHS_CLOCK_RESET_USB_INTERRUPT_ENABLE_VREG(index);
     *(usbRegMap2BaseAddress) |= 0x04;
    }
     
    with:
     
    PLIB_INLINE SFR_TYPE* _USBHS_CLOCK_RESET_USB_INTERRUPT_ENABLE_VREG(USBHS_MODULE_ID i)
    {
        switch (i) {
            case USBHS_ID_0 :
                return &USBCRCON;
            case USBHS_NUMBER_OF_MODULES :
            default :
                return (SFR_TYPE*)-1;
        }
    }
     
    This is understandable, but in 2.06 I have:
     
    PLIB_TEMPLATE void USBHS_GlobalInterruptEnable_Default( USBHS_MODULE_ID index )
    {
        /* Get pointer to the USBCRCON register and enable the global interrupt
         * register */
        volatile __USBCRCONbits_t * usbcrcon = (__USBCRCONbits_t *)(index - 0x5F000);
        usbcrcon->USBIE = 1;
    }
     
    This is to point to the usbcrcon register by subtracting a magic number from, I guess, a fixed reference index.  Not really sure how this works.
     
    I did some additional experimenting and found out if I copied the default routine directly into the drv_usbhs file, it works.  Apparently, it is not using the correct usbhs proc file even though the correct proc is selected.  Not sure where this gets defined either for me to find which one it is selecting.  I did start with a fresh configurator output before reintegrating code.
    post edited by mautry - 2018/10/18 15:23:09
    #6
    Jump to:
    © 2018 APG vNext Commercial Version 4.5