How to properly process incoming data in a USB MSC disk application?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to properly process incoming data in a USB MSC disk application?

941 Views
andyteufel
Contributor III

Hi,

I'm developing a USB MSC disk application for a board based on an RT1010.

I have the following working:
- I receive a `kUSB_DeviceMscEventWriteRequest` event which sets up a buffer for the USB stack to fill.
- I receive a `
kUSB_DeviceMscEventWriteResponse` which contains the data received via USB.
- In the same place while handling the MSC event in `
USB_DeviceMscCallback()`, I pass the buffer to a function that handles the received data. That data could end up being sent via UART, written to Flash memory, etc.

The problem I have is that all of this is executed from `USB_DeviceMscCallback()` which is called from an interrupt context. What I want to do is buffer the received data in a queue, and process it later in a thread context.

I found an example project that seems to show what I'm looking for, but I don't understand how it works.

It looks like the example application changes something so that `USB_DeviceMscCallback()` is no longer called from an interrupt context, but from a thread context.

The application calls `xQueueReceive()`, not `xQueueReceiveFromISR()` when handling `kUSB_DeviceMscEventWriteRequest` .

How does the application make this work?

 

EDIT: another question would be: is it okay to make a blocking call to `xQueueReceiveFromISR()` in the USB interrupt context? Or what is the right way to handle write requests when my application doesn't have enough resources to buffer the incoming data?

Labels (1)
0 Kudos
7 Replies

904 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi @andyteufel ,

But the RT1010 USB MSC disk application also deal data in thread.

jingpan_1-1687255766950.png

The ISR routine only check what the interrupt event is and then send message to USB stack thread.

You can download RT685 SDK from MCUXpresso.nxp.com and review the usb_device_msc_disk project.

 

Regards,

Jing

0 Kudos

892 Views
andyteufel
Contributor III

The ISR routine only check what the interrupt event is and then send message to USB stack thread.

It's the message sending I have an issue with. As you point out, on `USBDeviceMscRecv()`, the MSC class callback gets called to handle the kUSB_DeviceMscEventWriteRequest event.

Then `xQueueReceive()` is called there, from an interrupt context, blocking until the queue has a buffer available.

My questions are:

Why `xQueueReceive()` and not `xQueueReceiveFromISR()`? In the screenshot you posted you can clearly see in the call stack that the first function is `USBDeviceEhciIsrFunction()`.

How is the application affected if the queue blocks the execution of the interrupt?

How can I handle the case where my application is not returning the buffers to the queue fast enough so that `xQueueReceive()` returns a buffer immediately?

Thanks for your help. I hope my questions are understandable.

0 Kudos

874 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi @andyteufel ,

Yes, it's different. You can see related code in USB_DeviceNotificationTrigger().

jingpan_1-1687318271748.png

USB_DEVICE_CONFIG_USE_TASK is only enabled in FreeRTOS project.

 

Regards,

Jing

 

 

 

0 Kudos

862 Views
andyteufel
Contributor III

Hi @jingpan ,

Sorry, but I don't understand your reply. It seems you're talking about something completely different or I'm missing the point. What's different?

I understand how the `USB_DEVICE_CONFIG_USE_TASK` definition works, I have no questions about that.

0 Kudos

825 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi @andyteufel ,

Why `xQueueReceive()` and not `xQueueReceiveFromISR()`? In the screenshot you posted you can clearly see in the call stack that the first function is `USBDeviceEhciIsrFunction()`.

A: You can see it's up to the RTOS. xQueueReceiveFromISR() is used in ISR routine. But here queue is received in thread.

jingpan_0-1687745220956.png

 

How is the application affected if the queue blocks the execution of the interrupt?

A: xQueueReceive() is blocked in thread, not interrupt.

How can I handle the case where my application is not returning the buffers to the queue fast enough so that `xQueueReceive()` returns a buffer immediately?

A:  Enlarge the buffer or give higher priority to this thread.

 

Regards,

Jing

0 Kudos

776 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi @andyteufel ,

You can refer to this post.

 https://community.arm.com/support-forums/f/keil-forum/26317/usb-mass-storage-high-latency-memory

I think if it is not to long to wait other device to ready, you can delay the response.

Or you can send stall to let host delay and then unstall to let host recover. Please see the USB_DeviceStallEndpoint() and USB_DeviceUnstallEndpoint(). Set mscHandle->needOutStallFlag=1 in kUSB_DeviceMscEventModeSelectResponse to send stall to host.

 

Regards,

Jing

0 Kudos

809 Views
andyteufel
Contributor III

Hi @jingpan ,

I figured out the thread/interrupt issue. 

Now, I just have a question regarding this:

How can I handle the case where my application is not returning the buffers to the queue fast enough so that `xQueueReceive()` returns a buffer immediately?

A:  Enlarge the buffer or give higher priority to this thread.

In my case this is not enough. My application forwards the received data to another component and it has to be sent synchronously, i.e. I can only send more data to the other component until it tells me it can receive more data.

So what I need is to somehow indicate the USB host that I can't handle more data at the moment and to retry later. Is something like this possible somehow?

0 Kudos