This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x RTOS: How to callback into USB Mass Storage Device driver from a non-Hwi context?

Hello.

I'm trying to alter the example USB MSC driver from the Processor SDK to read/write blocks from the SD card rather than the RAMDISK.  The problem I'm having is that my SD card read/write API needs to execute in the Task context but the USB handlers are executing in the Hwi context.  In fact the entire driver executes in the Hwi context as far as I can tell.  Normally, I would Event_post from the Hwi context to notify an Event_pend'ing Task but in this case it is really not clear how to asynchronously callback into the USB MSC driver when the Task-processing is finished (i.e. a block has been read and is ready to be sent).  

Does anyone have any advice?

Kind regards

Brian

  • Hi,

    The RTOS team have been notified. They will respond here.
  • Brian,

    Can you explain "alter the example USB MSC driver from the Processor SDK to read/write blocks from the SD card rather than the RAMDISK"? Are you using AM335x as USB host to R/W a SD card? Or AM335x is the USB device and a part of its RAM (DDR) is used as a SD card, so a host/PC tries to R/W?

    The USB driver uses HWI. Can you explain the data flow in your case or some pseudo code showing what you are trying to do?

    Regards, Eric
  • Hi Eric

    My scenario is to have the AM335x act as a USB mass storage device that when connected to a USB host will expose the SD card connected to its SD peripheral.  This is exactly the same as the example code provided with the Processor SDK at:

    pdk_am335x_1_0_2/packages/ti/drv/usb/examples/bios/dev_msc_main.c

    except that instead of using the block read/write functions in ramdisk.c, I would like to replace them with my own block read/write functions that read/write blocks from the SD card peripheral.  Although, reading from a RAMDISK might be acceptable in the Hwi context, I would like to keep the potentially lengthy process of reading/writing blocks from the SD card in the Task context.

    My code is same as the example except that in the usbdmscglue.c file, I have replaced the RAMDISK block R/W functions with my own SD card block R/W functions.  This however obviously doesn't work because my block R/W functions expect to be called in the Task context.  For example, the USBMSCStorageRead function is called in the Hwi context but reading the SD card is a process that blocks which we cannot do in an Hwi context.

    As a first attempt to alleviate this issue I've tried using SYS/BIOS Events where instead of calling the core interrupt handler, I instead Event_post to a blocking task which then makes the call instead:

    #define onUSBInterrupt Event_Id_00
    
    typedef struct {
    	Event_Handle hEvents;
    	Hwi_Handle hwiHandle;
    	Task_Handle taskHandle;
    	bool task_started;
    
    } LocalData;
    
    static LocalData self;
    
    /* main entry point for DWC core interrupt handler with USB Wrapper setup
     * Matching interrupt call-back function API */
    static void hwiCoreIntrHandler(UArg arg) {
    	//USB_coreIrqHandler(((USB_Params*) arg)->usbHandle, (USB_Params*) arg);
    	Hwi_disableInterrupt(USB0_INT);
    	Event_post(self.hEvents, onUSBInterrupt);
    }
    
    void usbdIntrConfig(USB_Handle usbHandle, USB_Params* usbDevParams) {
    	Hwi_Params params;
    	Hwi_Params_init(&params);
    
    	/* Construct Hwi object for this USB interrupts. */
    	params.arg = (uintptr_t) usbDevParams;
    	params.priority = HWI_PRIORITY_USB;
    
    	/* Initialize the object ISR fucntion with application ISR */
    	self.hwiHandle = Hwi_create(USB0_INT, hwiCoreIntrHandler, &params, NULL);
    
    	USB_irqConfig(usbHandle, usbDevParams);
    }
    
    static Void taskUsb(UArg a0, UArg a1) {
    	USB_Params usb_dev_params;
    	USB_Handle usb_handle;
    
    	//delayTimerSetup();
    
    	/* Initialize the RAMDisk */
    	//RAMDISKUtilsInit((uint8_t *) gRamDisk, sizeof(gRamDisk));
    	usb_dev_params.usbMode = USB_DEVICE_MSC_MODE;
    	usb_dev_params.instanceNo = 0; /* USB port # */
    	usb_dev_params.usbClassData = (void*) &g_sMSCDevice;
    
    	usb_handle = USB_open(0, &usb_dev_params);
    
    	if (usb_handle == 0) {
    		System_printf("Failed to open USB driver \n");
    		System_flush();
    		while (1) {
    			Task_sleep(1000);
    		}
    	}
    
    	usbdIntrConfig(usb_handle, &usb_dev_params);
    
    	System_printf("Done configuring USB and its interrupts. \n");
    	System_flush();
    
    	while (1) {
    		Event_pend(self.hEvents, onUSBInterrupt, Event_Id_NONE,
    				BIOS_WAIT_FOREVER);
    
    		USB_coreIrqHandler(usb_dev_params.usbHandle, &usb_dev_params);
    		Hwi_enableInterrupt(USB0_INT);
    	}
    }
    
    void Usb_init() {
    	memset(&self, 0, sizeof(LocalData));
    	self.hEvents = Event_create(NULL, NULL);
    }
    
    void Usb_start() {
    	if (!self.task_started) {
    		Task_Params params;
    		Task_Params_init(&params);
    		params.priority = TASK_PRIORITY_USB;
    		self.taskHandle = Task_create(taskUsb, &params, NULL);
    		self.task_started = true;
    	}
    
    }

    However this crashes deep in SYS/BIOS Task code, probably because the USB_coreIrqHandler() function assumes Hwi context.  

    The USB gadget driver code seems to be written with the assumption that when the USB host requests data, that it can get the data and write it immediately back to the endpoint FIFO without ever leaving the original interrupt context.  I need to be able to block while getting the data to fill the USB request but I don't see any (obvious) way to do this with the USB driver provided in the Processor SDK.

    Kind regards

    Brian

  • Hi Brian

    Sorry for the delay.

    I didn't see anything wrong what you did. So I tried replicating it here, and the device MSC example still worked fine. No crash.

    Since I don't have any code that writes and reads the SD card, I still use RAM disk on the back end.  I added some printf to the UART in the ramdisk write and read function to slow them down. The  interrupt handler (hwiCoreIntrHandler) posts event into the USB task like you did. 

    Task function

    //*****************************************************************************
    // task function
    //
    //*****************************************************************************
    Void taskFxn(UArg a0, UArg a1)
    {
        USB_Params  usb_dev_params;
        USB_Handle  usb_handle;

        consolePrintf("\nRTOS USB Dev MSC example!!\n");

        /* Initialize the RAMDisk */
        RAMDISKUtilsInit((uint8_t *)gRamDisk, sizeof(gRamDisk));

        usb_dev_params.usbMode = USB_DEVICE_MSC_MODE;
        usb_dev_params.instanceNo = USB_DEV_INSTANCE;  /* USB port # */
        usb_dev_params.usbClassData = (void*)&g_sMSCDevice;
        
        usb_handle = USB_open(usb_dev_params.instanceNo, &usb_dev_params);

        if (usb_handle == 0)
        {
            consolePrintf("Failed to open USB driver\n");
            while(1)
            {
                Task_sleep(1000);
            }
        }

        usbdIntrConfig(usb_handle, &usb_dev_params);

        consolePrintf("Done configuring USB and its interrupt. Example is ready!\n");

        while(1)
        {
            /* Main while loop. All USB dev events are handled in interrupt context */
            Event_pend(hEvents, onUSBInterrupt, Event_Id_NONE,
                    BIOS_WAIT_FOREVER);

            USB_coreIrqHandler(usb_dev_params.usbHandle, &usb_dev_params);
            HwiP_enableInterrupt(SYS_INT_USB0);
        }
    }

    ISR function:

    /* main entry point for core interrupt handler with USB Wrapper setup
     * Matching interrupt call-back function API */
    static void hwiCoreIntrHandler(UArg arg) {
        HwiP_disableInterrupt(SYS_INT_USB0);
        Event_post(hEvents, onUSBInterrupt);
    }

    Does your code works if you keep the RAM disk?

    Best regards

    -Thanh

  • Just wondering if you still have any problem.

    Best regards

    -Thanh