usb_control_msg가 완료되는 데 0.25초가 걸리는 이유는 무엇입니까?

usb_control_msg가 완료되는 데 0.25초가 걸리는 이유는 무엇입니까?

통화를 통해 USB 장치에 동기화 제어 메시지를 보내고 있습니다 usb_control_msg. 완료하는 데 0.25초가 걸립니다. 이것이 정상적인/예상된 것입니까? USB 포트는 USB 3.0 입니다. 이 장치는 Cypress FX3 모듈입니다. Windows 시스템(동일 포트, 장치, FX3 펌웨어)에 대한 유사한 테스트에서는 더 짧은 시간에 각 메시지가 반환되었습니다. Linux에서는 전송된 첫 번째 메시지를 완료하는 데 10마이크로초가 걸렸고 다음 19개 메시지를 완료하는 데 약 0.25초가 걸렸습니다. 그런 다음 또 다른 메시지가 매우 빠르게 완료되고, 이어서 또 다른 19개 정도의 메시지가 모두 매우 느리게 완료됩니다. 또한, 8바이트 이상의 설정 데이터가 포함된 제어 메시지를 보낼 수 없습니다. 비동기 메시징을 구현해 보려고 하는데 동기 호출에 대해 이 동작을 개선할 수 있는지 알아두면 좋을 것 같습니다.

ktime_t start_time = ktime_get();
int ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), 0, 0x40, 0, 0, &command_data_payload, 8, 5000);

if (ret < 0)
   printk(KERN_ERR "Messaged failed: %d\n", ret);
else
   printk("message took: %llu\n", ktime_get() - message_start_time);

정정: 비교에 사용 중인 Windows 애플리케이션이 동기 호출을 사용하는지 비동기 호출을 사용하는지 모르겠습니다. 비동기 호출을 사용하여 테스트를 구현해 보겠습니다.

업데이트: 비동기 호출을 사용하면 메시지가 더 빠르게 전송되지만 완료 콜백을 호출하는 데 여전히 0.25초가 걸립니다. 20개의 메시지가 순차적으로 전송되면 그 중 1개는 매우 짧은 시간에 완료되고 나머지는 각각 0.25초가 걸립니다. 어쩌면 지연은 FX3 USB 장치 모듈의 기능일 수도 있습니다. 또한 Windows를 자세히 살펴보면 각 메시지를 완료하는 데 대부분 0.25초가 걸리며 일부 메시지는 더 빨리 완료됩니다.

답변1

비동기 메시지가 순차적으로 전송되기 때문에 빠르게 발행되는 것으로 추측되지만, USB 장치의 완료 콜백 및 응답이 발생하는 데 여전히 0.25초가 소요되며 지연은 Cypress FX3 모듈 때문입니다. 비동기 메시지에 대한 코드도 포함했습니다.

static struct usb_ctrlrequest ctrl_request;
static ktime_t last_time = 0;

static void write_control_callback(struct urb *urb)
{
   ktime_t now_time = ktime_get();
   if (last_time != 0)
       printk("skel_write_bulk_callback: %llu\n", now_time - last_time);
   last_time = now_time;
}

static long send_command(uint8_t * command_data_payload)
{
   int ret;
   struct urb * cUrb;
   void * buf;

   cUrb = usb_alloc_urb(0, GFP_KERNEL);
   if (!cUrb)
      return 1;

   buf = usb_alloc_coherent(device, 32, GFP_KERNEL, &cUrb->transfer_dma);
   if (!buf)
      return 1;

   memcpy(buf, command_data_payload, 32);  

   ctrl_request.bRequest = 0;
   ctrl_request.bRequestType = 0x40;
   ctrl_request.wValue = 0;
   ctrl_request.wIndex = 0;
   ctrl_request.wLength = 32;

   usb_fill_control_urb(cUrb, device, usb_sndctrlpipe(device, 0), (unsigned char*)(&ctrl_request),
buf, 32, skel_write_bulk_callback, NULL);

   ret = usb_submit_urb(cUrb, GFP_KERNEL);
   if (ret)
      printk("could not submit urb\n");
}

경고하다! ! ! :이 코드에서는 할당된 버퍼를 제대로 해제하지 않습니다.

관련 정보