STM32CubeMXが生成してくれるUSB MiddleWareには、単純なBULK transferのexampleが無いんです.HID,Audio,CDC,DFUなどのClass exampleの中にBULK transferしている場所が見当たらないというのが正しい.別の手段か別の名前で実装しているには違いないのだろうけど.
というわけでUSB BULK transferをするまでの試行錯誤を書いてゆきます.
環境:
Nulceo H723Z USB device FS (12Mbps)
STM32CubeIDE 1.15 (windows)
HOSTマシン Linux
LinuxのUSB library usblib-1.0.27
usblibについて注意:
Linuxマシンにはusblib-1.0.25がインストされていましたが、最新はusblib-1.0.27のようですので
1.0.27をインストしました.
こちらのページによると、apt installでやると1.0.25がインストされちゃうと警告しています.ただし、こちらのページ通りですとインストまでは通りませんでした.configureが無かった.
ーーーー
まずは、STM32CubeMXで生成したDFU Classを使ってみる.
DFUを選んだ理由は、HIDだと定期的アクセスが生じてめんどくさい気がした、Audioは複雑すぎるだろう、といった理由.DFUはfirmware updateするためのclassらしいのでシンプルにdata転送に特化してるんじゃないのかなと思ったりして.
生成されたDFU classほぼそのままをNucleoに焼いて、Linuxマシンに接続し、どんな素性のUSB deviceが接続されたんだろうねぇとlsusbで表示させてみる.少し略すがこんな感じ.
Device Descriptor:
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0xdf11 STM Device in DFU Mode
bcdDevice 2.00
bNumConfigurations 1
Configuration Descriptor:
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 2 HIRASAKA
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Descriptor:
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 254 Application Specific Interface
bInterfaceSubClass 1 Device Firmware Update
bInterfaceProtocol 2
iInterface 6 @Internal Flash
Device Firmware Upgrade Interface Descriptor:
bDescriptorType 33
bmAttributes 11
Will Detach
Manifestation Intolerant
Upload Supported
Download Supported
wDetachTimeout 255 milliseconds
wTransferSize 1024 bytes
bcdDFUVersion 1.1a
感想としては、
・シンプルだなぁ (Audio classはもっと複雑)
・EPの記述無し
・control EPで64BYTE packetでトロトロ流す感じなのだろう
・細かいところはDFU Classにぶん投げ
ーーーー
次に、Linux HOSTからSTM32をopenしてみるなり.
コンパイルの呪文はこれにて.
gcc eprw.c -I/usr/include/libusb-1.0 -lusb-1.0 -o eprw
↓Linux HOSTは概略このcodeでopenできてる.
#include <libusb.h> // usblib1.0
struct libusb_device_descriptor desc;
libusb_device_handle *h_dev;
unsigned char text[512];
int main(int argc, char *argv[]){
libusb_device **list;
libusb_device *found = NULL;
// search & open
libusb_init( NULL );
int dcnt = libusb_get_device_list(NULL,&list); ①
if(dcnt<0) exit(1);
printf("There are %d USB device.\n",dcnt);
for(int i=0;i<dcnt;i++) {
libusb_device *device = list[i];
libusb_get_device_descriptor(device, &desc); ②
int ret = libusb_open(device, &h_dev); ③
if(ret==0) {
libusb_get_string_descriptor_ascii(h_dev, desc.iManufacturer, text, sizeof(text)); ④
int vid = desc.idVendor; ④
int pid = desc.idProduct; ④
printf("%d %04x/%04x %s\n",i,vid,pid,text);
if(strcmp("HIRASAKA",text)==0) { ⑤
found = device;
printf("-->found my device.\n");
}
libusb_close(h_dev);
}
}
libusb_free_device_list(list,1);
libusb_open(found, &h_dev); ⑥
}
まずはopenだけしかやってません.
libusbの作法通りにやってます~
①list[]にUSB deviceをリストする
②各リストのdevice descriptorを取得
③各々をお試しopen
④Manufacturer名称、VID、PIDを抽出
⑤Manufacturer名称=HIRASAKAだったら目的のdeviceだ
⑥改めて目的のdeviceをopen
こうゆう探すやりかたじゃなくて、VID,PIDで狙い撃ちopenする方法もありますが割愛します.
ーーーー
上記⑥でopenしたのに続き、、、kernel driverを起動したりするおまじない.
libusb_set_auto_detach_kernel_driver( h_dev , 1 );
libusb_set_configuration( h_dev , 1 );
libusb_claim_interface( h_dev , 0 ); // select interface
さらに、EndPointのmax packet sizeを読んでみる.正しくconfig出来れば64などが表示されるはず.
int psize0 = libusb_get_max_packet_size( found, 0 );
int psize1 = libusb_get_max_packet_size( found, 1 );
int psize2 = libusb_get_max_packet_size( found, 2 );
int psize3 = libusb_get_max_packet_size( found, 3 );
int psize4 = libusb_get_max_packet_size( found, 4 );
int psize5 = libusb_get_max_packet_size( found, 5 );
printf("%d %d %d %d %d %d\n", psize0, psize1, psize2, psize3,\
psize4, psize5);
ところが、printf結果は、「-5 -5 -5 -5 -5 -5」になってしまった.-5はNOT FOUNDのerr codeなので、EP0~EP5が定義されてないことを意味する.descriptorにEPが書かれてないので無理も無かろうと思う.
DFU Classを雛形にするのは諦めます.
以後はCDC Classに切り替えます.
CDC Classですと、「-5 64 -5 -5 -5 -5」の表示になり、EP1がmax packet size 64に設定されていることがわかる.
CDC ClassのdescriptorをチェックするとEP2IN,EP1OUT,EP1INの3つのEP descriptorが存在する.これらのうちEP1の64bytesが表示されたが、EP2の8bytesが表示されなかったのは理由不明.
Endpoint Descriptor:
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 16
Endpoint Descriptor:
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
Endpoint Descriptor:
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
第一回はこれまでにしとうございます.
かしこ