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.

RTOS/AM3358: USB Bulk full duplex issue

Part Number: AM3358

Tool/software: TI-RTOS

Hi

I'm working with evmAM335x. In my code i have two tasks to implement usb Bulk device comunication

In Task1 I initialize the usb and block inside USBD_bulkRead() waiting for a msg from the host.

In Task2 I block inside a Mailbox.

Void Task1 (UArg a0, UArg a1)
{
    usbInit(); // Function that initialize usb bulk instance.
    
    Mailbox_Handle mbx = (Mailbox_Handle)a0;

    while(1){
	uint32_t rxBytes;
        if (g_ulFlags & COMMAND_STATUS_UPDATE){
            g_ulFlags &= ~COMMAND_STATUS_UPDATE;

            if (g_bulk_state == BULK_STATE_CONNECTED){
		usb_osalDelayMs(500);
		g_bulk_state = BULK_STATE_READY;
            }
        }
		
	if (g_bulk_state = BULK_STATE_READY){
	    memset(g_bulkRxBuffer, 0, MAX_TRANSFER_SIZE);
	    USBD_bulkRead(g_usbHandle, g_bulkRxBuffer, &rxBytes);
			
	    if(rxBytes > 0){
		Mailbox_post(mbx, g_bulkRxBuffer, BIOS_NO_WAIT);
	    }
	}
    }
}


Void Task2 (UArg a0, UArg a1)
{
    Mailbox_Handle mbx = (Mailbox_Handle)a0;
	
    while(1){
        if(Mailbox_pend (mbx, g_bulkTxBuffer, BIOS_WAIT_FOREVER)){
	    if (g_bulk_state == BULK_STATE_READY){
                USBD_bulkWrite(g_usbHandle, g_bulkTxBuffer, 15);
	    }
	}
    }
}

I can transmit some data through USBD_bulkWrite() while another task is blocked in USBD_bulkRead(), but when I receive data from host the code jumps to syscall _exit();

I try control this behavior, meaning that in other test I make sure that USBD_bulkWrite() is not called when USBD_bulkRead() is blocked. And this works great, but I only can respond to host's messages. With this workaround I can never send  unsolicited messages to the host.

Can someone help me?

  • Hi,

    Can you clarify what Processor SDK RTOS release you used? USBD_bulkRead() and USBD_bulkWrite() are USB driver APIs, but those task1 and task2 just your own code, correct? What is the task priority for both?

    Why there is a usbInit() inside Task1? How do you know the Task1 will run first to make sure usbinit is called first? Once task1 runs, it goes into a while(1) loop, how do you switch to task 2 even you has a Mailbox_post(). I thought you need task_sleep inside?

    Regards, Eric

  • Hi lding

    Can you clarify what Processor SDK RTOS release you used? I'm using SYS/BIOS 6.52.0.12 and PDK 1.0.11

    USBD_bulkRead() and USBD_bulkWrite() are USB driver APIs, but those task1 and task2 just your own code, correct? Yes

    What is the task priority for both? Task1.priority = 1 and Task2.priority = 4

    Why there is a usbInit() inside Task1? usbInit is there because early i made an example to test the usb driver and it works. So i left the initialization of usb driver in Task1. This is not a problem beacuse usb implementations it works good. 

    How do you know the Task1 will run first to make sure usbinit is called first? Before the BIOS_start() i set the priority to the task. It runs mayor priority first. and if not the task 2 wait for message in Mailbox_pend.

    Once task1 runs, it goes into a while(1) loop, how do you switch to task 2 even you has a Mailbox_post(). I thought you need task_sleep inside? when the Usb is attached to host g_ulFlags set the COMMAND_STATUS_UPDATE bits in usbdbulkEventCallback() (usbdbulkEventCallback() this is called from USB LLD, and interrupts any task). when this bit is set on g_ulFlags for the code in Task1, it set g_bulk_state = BULK_STATE_READY cause and then this task is blocking on USBD_bulkRead(). Task2 is unblocking for another Task connect through UART to terminal, so i can control when Task2 is unblocking to send through usb what i send through terminal.

    The issue is that i cant stay blocking in USBD_bulkRead() and transmit in Task2, Because when i receive the response in USBD_bulkRead() I send the Post and then when i try to receive again this fail, and the code call syscall _exit().

    NOTE: the Mailbox on task1 is different a Mailbox on Task2. So when Task2 blocks on Mailbox_pend(), this is not unblocking for Mailbox_post() on Task1. Sorry for the misunderstanding

  • Hi,

    From your code, when task1 runs and gets data from host, it posts to mailbox so the task2 can run to write to host. In other word, task1 can block task2, but not vice versa. So when the task2 runs, the task1 still try to read from host. I am not sure if bulk protocol can be duplex or not. But seems you already find it can only be simplex.

    For the "I try control this behavior, meaning that in other test I make sure that USBD_bulkWrite() is not called when USBD_bulkRead() is blocked. And this works great, but I only can respond to host's messages. With this workaround I can never send unsolicited messages to the host.". I felt that USB host needs to write to bulk device first before the bulk device can write to host. That is you can't send the unsolicited message to host.

    Our USB bulk example pdk_am335x_1_0_11\packages\ti\drv\usb\example\usb_dev\bulk is one task (not duplex) with host writes to device first, then bulk device echo back. Does this make sense or you have a different expectation and some USB doc explained that bulk can be duplex and device can send message to host first?

    Regards, Eric
  • Hi,

    Also, I find this: docs.microsoft.com/.../usb-bulk-and-interrupt-transfer

    "The endpoint is a unidirectional and data can be transferred either in an IN or OUT direction. Bulk IN endpoint is used to read data from the device to the host and bulk OUT endpoint is used to send data from the host to the device."

    "Like all other USB transfers, the host always initiates a bulk transfer. "

    Regards, Eric
  • Hi,

    I understand now that "Like all other USB transfers, the host always initiates a bulk transfer".
    Texas Instruments USB Bulk implementation blocks on USBD_bulkRead() until some data is received or USB is detached. Is there some implementation or some trick that can be used to unblock USBD_bulkRead(), so that it would let me do polling?