Loop frequency enhancement

I need advice.

I have a usb device, and I`ve written code to get data from the device.
The code:
do{
usbd_setup_isochronous(urb, URB_DIR_IN | URB_ISOCH_ASAP, 0 mem, max_packet_size );
usbd_io( urb, conn_pipe, cbf, NULL,USBD_TIME_DEFAULT);
pthread_mutex_lock(&io_mutex);
pthread_cond_wait(&io_cond, &io_mutex);
pthread_mutex_unlock(&io_mutex);

}while(…)

cbf is as follows:
void cbf(struct usbd_urb *, struct usbd_pipe *, void *){
pthread_mutex_lock(&io_mutex);
pthread_cond_signal(&io_cond);
pthread_mutex_unlock(&io_mutex);
}

My problem is that, loop frequency is about 90Hz. Pooling interval for isochronous devices is 1ms. Is there any way to make the loop to go faster? Without mutexes and condvar code speeds up significantly, it hangs up the usb stack, however.io_mutex);
pthread_cond_signal(

Wallace,

The polling interval for USB may be 1 ms but that doesn’t mean there is any data there to read in your CBF.

Without seeing more of your code its hard to guess. But are you signaling the condition (pthread_cond_signal) only when there is data read or every 1 ms? Normally you only want to signal when there is data. So are you sure you are missing data from the USB device or is the device only sending at a 90 Hz rate?

QNX mutex’s and condvars are very fast. Much faster than 90 Hz I can assure you.

Tim

Tim,

When you say “the device only sending at a 90 Hz rate?” what do you mean?

The device is usb audio codec (pcm2902B) with sinusoidal wave plugged to input channel, so I`m pretty sure there are data to receive every 1ms. What is more, when generated plots from gathered data they look like some frames are missing.

I believe that condvars and mutexes are much faster, but the frequency drops down when used. Without synchronization mechanism program is unstable (system stops responding).

The last thing I noticed is fact, that when IO code looks that way:

usbd_get_frame(device, &fnum, &flen);
usbd_setup_isochronous(urb, URB_DIR_IN | URB_ISOCH_ASAP, fnum, mem, flen);
usbd_io( urb, conn_pipe, cbf, NULL,USBD_TIME_DEFAULT);

Its pretty fast, but flen is much bigger than max_packet_size, they are respectively 1024 and 98. And gathered data is a part of time-repeatable data (but it doesnt even close to sin shape) and 0.

Wallace,

Ah, OK, good to know. I had no idea what USB device you were connecting. I wasn’t sure if it was some kind of Digital/Analog I/O card that only sent data 10 or 100 times a second.

Not sure where you get max_packet_size from (the doc’s on the USB device?). I would use the code above. It’s very possible (likely) that the transferred data from the USB device contains multiple packets of data (similar to how Ethernet packets can contain 1024 bytes and could contain 10 packets of 98 bytes).

When you use the above code, how much data is being transferred? If it’s more than 98 bytes, are you handling the possibility that you are getting multiple packets in that data?

Tim

Tim,

Sorry for late response, but im suffering from lack of time. Ive taken a closer look at the code (faster version), it appears not to work correctly. I`ve used usbd_urb_status. Returned value is always EBUSY, and completion status never equals to USBD_STATUS_CMP_ERR. I think, data I get using the faster code version is just rubbish.

max_packet_size is value I received from endpoint descriptor (it equals the value mentioned in devices datasheet).

Im handling possibility that Im getting multiple packets in data transmitted from device. Program just writes data from buffer (which data from device are transferred to) to file as short type, so every packet I get is saved in file. As I use write() function is not human-readable format. The another program reads the file, and save the data as column of numbers readable for human. This file is passed as data input for plot.

Wallace,

I went back and re-read all your postings. You don’t mention which version of QNX you are running. In the 6.4 Doc’s for usbd_io() it says that the function parameter (where you are stuffing cbf) is not supported. Only synchronous transfers are allowed.

qnx.com/developers/docs/6.4. … bd_io.html

So I just want to make sure you aren’t going down the wrong path in 6.4. I do not know about the 6.5 DDK as I didn’t see the doc’s for it. It may well still be the same as 6.4.

I agree with you about the rubbish part when you don’t have the Condvar. In those cases I expect you are just returning immediately and actually reading nothing from the USB stack. You could probably verify this if you wanted by setting the memory transfer block to something like 0xFF in every byte and seeing if you got that back. But I don’t think you need to do that.

When you make your call to usbd_alloc (which you don’t show), how much space are you allocating for the transfer data (your mem variable)? Is it 98 or 1024? Just curious to know if how big you’ve made this since you won’t be able to get 1024 bytes unless you reserved that much space.

Tim

Tim,

I`ve tried usbd_alloc with allocating both, 98 and 1024 bytes.

The system version is 6.4.1, so I have to admit that, I did not read the usb ddk docs carefully enough.

Ok, so now i understand, that I have to use
usbd_setup_vendor - ddk docs does not mention how to set up synchronous mode.

and then,
usbd_io

If the callback must be set to NULL, how to signalize that usbd_io has finished?

Wallace,

When the call returns. With synchronous transfers the usbd_io call will block until data is returned (UDBD_TIME_INFINITY) OR UDBD_TIME_DEFAULT (not sure what that’s set to but it’s in case you don’t want to wait forever for data and want to do some processing before returning to check again for data being available).

Just be sure to check the error code when usbd_io returns to make sure the USB device wasn’t removed.

Tim