CH552でUSBのserial number
ch552を使ってUSB機器を作れるようになったが, ch55xduinoとch554_sdcc_usb_blinkyを組み合わせた方法では,serial numberを記述することが出来なかった. 同じ機器を同時にいくつも接続した場合に,それらを区別するのにはserial numberが便利である. そこで,前回使ったプログラムを改造して,serial numberを使えるようにした.
まずは,serial numberのデータを他の文字列を参考にして定義する.
#ifndef USB_CUST_PRODUCT_SERIAL
#define USB_CUST_PRODUCT_SERIAL_LEN 10
#define USB_CUST_PRODUCT_SERIAL {'0','1','2','3','4','5','6','7','8','9'}
#endif
このデータから,その文字列を表すdescriptorを作る.
__code struct {uint8_t bLength; uint8_t bDscType; uint16_t string[USB_CUST_PRODUCT_SERIAL_LEN];} sd003 = {
sizeof(sd003), USB_DESCR_TYP_STRING,
USB_CUST_PRODUCT_SERIAL
};
そして,他の文字列を処理している部分と同様に,以下のプログラムを追加する.
else if(UsbSetupBuf->wValueL == 3)
{
UsbIntrDescr = (uint8_t*) sd003;
len = sizeof(sd003);
}
これで,serial numberが扱えるようになる. 実際,USBに挿してdmesgで確認すると,SerialNumber:の後に文字列が表示されている.
しかし,それぞれのマイコンにプログラムを書き込む時に,異なったserial numberを与えたり,それを管理するのは面倒である. そこで,ch552のunique IDをserial numberにすることにした. 上では変更することが無いので,flash上にデータがあり,__codeと定義したが,それを変更できるようにvolatile __xdataと変更する. そして,USBの初期化の部分で,sd003の文字列の部分をunique IDを16進数に直した文字列に書き換える.
uint16_t ser;
uint8_t num,i;
ser=*(__code uint16_t*)ROM_CHIP_ID_HX;
for(i=0;2>i;ser>>=4){num='0'+(ser&0x0f); sd003.string[1-i++]=num>'9'?num+7:num;}
ser=*(__code uint16_t*)ROM_CHIP_ID_HI;
for(i=0;4>i;ser>>=4){num='0'+(ser&0x0f); sd003.string[5-i++]=num>'9'?num+7:num;}
ser=*(__code uint16_t*)ROM_CHIP_ID_LO;
for(i=0;4>i;ser>>=4){num='0'+(ser&0x0f); sd003.string[9-i++]=num>'9'?num+7:num;}
unique IDのデータはflashの上にあり,これをどうやって読み出すかに少し苦労したが,アドレスをポインタとしてキャストして,それを数値に変換することによって読み出せた. flash上にあることを示すために__codeをつけるというのも独特である.
少しずつUSBのデータ処理の仕方の理解が進んできているが,それを生かして今後もいろいろなUSB機器を作ることになるだろう.