Top
HIDaspx
DownLoad
HIDasp高速化
制作
AVR関係
AVR_Monit
AVR_term
W32_term
HIDmon88
HIDtester
usbRS232
Arduino2313
デジタルテスター
ATmega88生活
KeyBoardマニア
KeyBoardマニアII
Arduino400
PICライター
ARMライター
赤外線リモコン
ARM
STM32ブートローダー
STM8S-Discovery改造
STM8S-OpenOCDライター
LPCXpresso
LPC用ブートローダー
NXP用LPCUSB
NXP用ブートローダー
MARY基板
LPC1114FN28
OpenOCD JTAGアダプター
OpenOCDビルド方法
arm-gccビルド方法
mapleIDEの改造
libmapleで仮想COM
PIC32
PIC32MX
Pinguinoで遊ぼう
ブートローダーを作る
シリアルブートローダー
USB仮想シリアル
USBカスタムデバイス
USB簡易モニター
USBオシロスコープ
USBホスト
PIC32でBluetooth
USBAudio
USBStudy
VGA出力に挑戦
BASICを動かす
WinUSB
勝手に改蔵*PIC32
PIC18F
HIDブートローダー
AVR/PIC両用ライター
ARMライター
usb汎用クラス
usbシリアル変換
usbキーボード変換
sdccを使いこなす
mcc18を使いこなす
HIDmon-2550
HIDmon-14K50
PICmonitor
試行錯誤の記録
UBWを試す
旧HIDboot
PIC18F2550試用記
PIC18F4550試用記
その他マイコン
NEC78K
RX62N
SH2A
H8
FM3
XPからubuntuに乗り換え
Android
Xen-hypervisor
Windows8カスタマイズ
開発日記
2015-04
ノウハウ
AVRUSB_Tips
HIDasp情報
汎用USB-IO
・
リンク
フリースペース
ゲストブック
旧コンテンツ
WinVista
インターフェース考
最新の20件
2022-07-25
2008-10
HIDasp高速化
H8/3048F
AutoTicketLinkName
2021-12-11
FormattingRules
2021-12-08
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/V-Z
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/H-K
2020-02-23
YukiWiki
PHP
PukiWiki
WikiWikiWeb
2018-12-19
SandBox
InterWiki
2015-05-07
2015-04
2015-05-02
MenuBar
編集
差分
PIC32MX_USBCDC の編集
-- 雛形とするページ --
(no template pages)
[[PIC32MX]] #contents *PIC32MXで仮想シリアルポートを実装してみる。 [#p1a04499] ''2通りの方法があります'' -1つめは、Pinguinoのお手軽スケッチをそのまま使う方法です。 -もうひとつは、MicroChipのUSB-CDCサンプルを使います。 ~ *Pinguinoのスケッチを使用してエコーバックサンプル。 [#a4f38fbd] -スケッチを使用するといっても、pde拡張子のままではROMに焼いたりいろいろ改造できませんので、 例によって、Pinguino環境でMakefileその他を用意してコマンドライン開発する環境に移します。 -user.c unsigned int counter=0; void setup() { pinmode(13, OUTPUT); } void loop() { static int cnt=0; static char buffer[256]; int numBytesRead = USB_Service_CDC_GetString( buffer ); if(numBytesRead>0) { CDCputs(buffer,numBytesRead); } cnt++; if( cnt >= 500000 ) { cnt=0; toggle(13); } } -ダウンロード:[[cdcecho.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcecho.zip]] -こうして出来た仮想シリアルポートのエコーバックサンプルに対して、規則的な繰り返しの文字データを送信し、同時に受信を行なって、その時間を計ります。(ベンチマーク) E:\cdcecho>w32term -p ==== COM Port List==== COM50:TxQue=0,RxQue=16384,Baud=0x66b70,BaudMax=0x10000000,Bits=0xc,SubType=6,Capa=cd COM1:TxQue=0,RxQue=4096,Baud=0x1006ffff,BaudMax=0x10000000,Bits=0xf,SubType=1,Capa=ff E:\cdcecho>w32term -c50 -t Entering Benchmark: Escape=^A .......................................................................................... .......................................................................................... ...................................................................... Benchmark end. 32000 bytes/812 ms, 39408 bytes/s (394080 bps) E:\cdcecho> -毎秒40kBのスループットになっていることがわかります。ボーレートでは(start/stop bitを加味すると)394kBPSです。 -ちょっと遅いですね。 *---考察します。 [#i7cb9167] -Pinguinoライブラリのcdcサンプルがどのような実装になっているかはあくまで推測です。 -毎秒40kBしか送り返せない、ということは、USBの1フレーム時間(1mS)に40byteしか返送されていません。 -FullSpeed(12Mbps)USBのパケット長は64byteなので、1フレーム時間にわずか1パケットしか返送されていません。 -しかも64byteではなくて40byteです。 ~ -これはおそらく、返送ルーチンがバイト指向になっていて、上限が40byteに制限されているのではないか、と推察します。 -以前にもARMのmapleライブラリのcdc実装がそれに似た感じになっていました。 -FullSpeed USBの性能としては、1フレーム時間に少なくとも10パケット程度は送出できます。 -これが、なぜ1パケットに制限されるか、というと、それはCDC ACMクラスのWindowsドライバーがそうなっているからで、1回のシリアルデータのバルク転送パケットのサイズが64byte未満だった場合は、後続データ無しとみなして、その1フレーム時間(1mS)内には次のパケットを受け取らないという仕様になっているからです。 ~ -USB-CDCデバイスでせっかくバルク転送が使用できるのに、HIDデバイス未満の転送速度しか得られないというのは''なんだか納得がいきません'' ~ *---次は、MicroChipのUSB-CDCサンプルを使って試してみます。 [#td696145] -ソースは長いのですが、一応肝の部分だけ抜粋します。 void ProcessIO(void) { BYTE numBytesRead; BlinkUSBStatus(); if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; if(buttonPressed) { if(stringPrinted == FALSE) { if(mUSBUSARTIsTxTrfReady()) { putrsUSBUSART("Button Pressed -- \r\n"); stringPrinted = TRUE; } } } else { stringPrinted = FALSE; } if(USBUSARTIsTxTrfReady()) { numBytesRead = getsUSBUSART(USB_Out_Buffer,64); if(numBytesRead != 0) { memcpy(USB_In_Buffer,USB_Out_Buffer,64); putUSBUSART(USB_In_Buffer,numBytesRead); } } CDCTxService(); } -実際の応答部分は、最後の8行分のところだけです。 -こちらのソースでは、受け取ったUSBパケットをそっくりそのままWindowsに返送しています。 -なので、1フレーム時間(1mS)に複数個のパケット(64byteパケットが連続して、最後に64byte未満のパケットが来る)が送られてきてもそれをそっくりそのまま返送するので効率がよいのです。 -(もちろん、バイト指向で再組み立てする方法でも64byte未満パケットに分断さえしなければスループットは低下しません。) ~ ビルド -Pinguinoコンパイラでビルドしますが、MchipのヘッダーとMchipのUSBアプリケーションフレームワークが必要です。 *ダウンロード [#b0bc3853] -[[cdcscope.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcscope.zip]] ~ -このcdcscope.zipで生成されるHEXファイルはBOOTLOADERからの書き込みとPicKit2からの書き込みの両方に対応しています。 -こういうふうになっています。 BFC0_0000+---------------+ | Jmp _start | <=== RESETで最初に実行される命令 | | | | |BOOTLOADERの一部| +---------------+ 9D00_0000+---------------+ | BOOTLOADER | BOOTLOADERに重なっている部分はアプリでは使用しません。 | | | | | | 9D00_2000+---------------+ (_reset) | Jmp _start | <=== BOOTLOADERからの起動により最初に実行される命令 | ============= | | 割り込みVECTOR| | ============= | |_start:初期化部| | | | アプリ本体 | | | 9D00_7FFF+---------------+ -BFC0_0000からの16バイトだけが、BOOTLOADERとアプリケーションで重複しますが、 -BOOTLOADERは9D00_2000〜9D00_7FFFの範囲内のみイレース、書き換えを行ない、それ以外の領域のHEXレコードを無視しますので、スタンドアローン、ブートローダー起動のどちらでも正しく起動します。 ~ ~ ~ ~ *ベンチマーク結果 [#q0f43147] E:\cdcscope>w32term -c50 -t Entering Benchmark: Escape=^A .......................................................................................... .......................................................................................... ...................................................................... Benchmark end. 32000 bytes/141 ms, 226950 bytes/s (2269500 bps) E:\cdcscope> -スループットは毎秒226kB (実効ボーレートで2.26M BPS)になりました。 ~ ~ ~ ------------- *USB - シリアル変換器 (Serial Emulator) を作る。 [#jcf74f3e] -FTDI FT232RのようなUSB-シリアル変換器を作成します。 -これは、MicroChipのUSBフレームワークのCDC Serial EmulatorをビルドすればOKです。 -MX220F032B用に移植したものを用意しました。 ''ダウンロード'' -[[cdcserial.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcserial.zip]] -ブートローダー起動、PicKit2ライター直接書き込みの両対応HEXになっています。 -Pinguinoのmips-gccとコマンドライン版Make(Pinguino付属)でビルドします。 ~ *移植の手順についての説明 [#gbc2be36] (1)チップ品種の変換 -HardwareProfile.h というヘッダーが各品種ごとのヘッダーを選択的にincludeするようになっていますので、 HardwareProfile_MX220F032B.h というヘッダーを用意して、それをインクルードするように書き換えます。 -HardwareProfile_MX220F032B.hヘッダーにはMX220F032Bの自作基板にあわせたピン配置の定義を書きます。 ~ (2)crt0.Sの用意 -メモリー配置をブートローダー起動、PicKit2ライター直接書き込みの両対応にするためと、メモリー節約のために、少し改造したcrt0.Sを用意しています。 -これは、ramfuncのコピーを省略してサイズを0x180 byte以下に抑え、割り込みベクターの手前に収まるサイズにしたものです。 -ついでに、割り込みベクターから、割り込みハンドラーへのJmp命令も書き足しています。 ~ (3)MakefileとObjs.makの用意。 -Objs.makはリンクしたいモジュールを列挙したものです。 ~ (4)main.cの改造 -MchipのサンプルコードはPIC18FやLowPinCountPIC,PIC24F,dsPIC33など数多くの品種をカバーしているために、#ifdef〜#endifの嵐になっています。 -これでは、あまりに見通しが悪いので、PIC32MX以外の記述は思い切って削除します。 -つぎに、main()関数の先頭、かつ割り込みベクター設定があればその直後にそれを上書きする形で下記の記述を追加します。 _CP0_SET_EBASE(_RESET_ADDR); // 割り込みベクターを9D00_2000 に変更する. - _RESET_ADDR はリンカースクリプトから供給されるシンボルラベルです。 -最後に、USBをポーリング実装でコンパイルするときに消滅する関数_USB1Interrupt()を補うための記述を入れます。 #if defined(USB_POLLING) // for crt0.S vector dummy; // Dummy Function (Never Called) // void __attribute__((interrupt,nomips16,noinline)) _USB1Interrupt(){} #endif -これはcrt0.SからJmp命令で飛んでくる関数ですが、ポーリングモードでは実在しませんので、ダミーとしてここに置きます。実際には割り込みませんのでここに飛んでくることはないです。 -(crt0.Sを毎回書き換えるのが面倒なのでCレベルで対処)
タイムスタンプを変更しない
[[PIC32MX]] #contents *PIC32MXで仮想シリアルポートを実装してみる。 [#p1a04499] ''2通りの方法があります'' -1つめは、Pinguinoのお手軽スケッチをそのまま使う方法です。 -もうひとつは、MicroChipのUSB-CDCサンプルを使います。 ~ *Pinguinoのスケッチを使用してエコーバックサンプル。 [#a4f38fbd] -スケッチを使用するといっても、pde拡張子のままではROMに焼いたりいろいろ改造できませんので、 例によって、Pinguino環境でMakefileその他を用意してコマンドライン開発する環境に移します。 -user.c unsigned int counter=0; void setup() { pinmode(13, OUTPUT); } void loop() { static int cnt=0; static char buffer[256]; int numBytesRead = USB_Service_CDC_GetString( buffer ); if(numBytesRead>0) { CDCputs(buffer,numBytesRead); } cnt++; if( cnt >= 500000 ) { cnt=0; toggle(13); } } -ダウンロード:[[cdcecho.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcecho.zip]] -こうして出来た仮想シリアルポートのエコーバックサンプルに対して、規則的な繰り返しの文字データを送信し、同時に受信を行なって、その時間を計ります。(ベンチマーク) E:\cdcecho>w32term -p ==== COM Port List==== COM50:TxQue=0,RxQue=16384,Baud=0x66b70,BaudMax=0x10000000,Bits=0xc,SubType=6,Capa=cd COM1:TxQue=0,RxQue=4096,Baud=0x1006ffff,BaudMax=0x10000000,Bits=0xf,SubType=1,Capa=ff E:\cdcecho>w32term -c50 -t Entering Benchmark: Escape=^A .......................................................................................... .......................................................................................... ...................................................................... Benchmark end. 32000 bytes/812 ms, 39408 bytes/s (394080 bps) E:\cdcecho> -毎秒40kBのスループットになっていることがわかります。ボーレートでは(start/stop bitを加味すると)394kBPSです。 -ちょっと遅いですね。 *---考察します。 [#i7cb9167] -Pinguinoライブラリのcdcサンプルがどのような実装になっているかはあくまで推測です。 -毎秒40kBしか送り返せない、ということは、USBの1フレーム時間(1mS)に40byteしか返送されていません。 -FullSpeed(12Mbps)USBのパケット長は64byteなので、1フレーム時間にわずか1パケットしか返送されていません。 -しかも64byteではなくて40byteです。 ~ -これはおそらく、返送ルーチンがバイト指向になっていて、上限が40byteに制限されているのではないか、と推察します。 -以前にもARMのmapleライブラリのcdc実装がそれに似た感じになっていました。 -FullSpeed USBの性能としては、1フレーム時間に少なくとも10パケット程度は送出できます。 -これが、なぜ1パケットに制限されるか、というと、それはCDC ACMクラスのWindowsドライバーがそうなっているからで、1回のシリアルデータのバルク転送パケットのサイズが64byte未満だった場合は、後続データ無しとみなして、その1フレーム時間(1mS)内には次のパケットを受け取らないという仕様になっているからです。 ~ -USB-CDCデバイスでせっかくバルク転送が使用できるのに、HIDデバイス未満の転送速度しか得られないというのは''なんだか納得がいきません'' ~ *---次は、MicroChipのUSB-CDCサンプルを使って試してみます。 [#td696145] -ソースは長いのですが、一応肝の部分だけ抜粋します。 void ProcessIO(void) { BYTE numBytesRead; BlinkUSBStatus(); if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; if(buttonPressed) { if(stringPrinted == FALSE) { if(mUSBUSARTIsTxTrfReady()) { putrsUSBUSART("Button Pressed -- \r\n"); stringPrinted = TRUE; } } } else { stringPrinted = FALSE; } if(USBUSARTIsTxTrfReady()) { numBytesRead = getsUSBUSART(USB_Out_Buffer,64); if(numBytesRead != 0) { memcpy(USB_In_Buffer,USB_Out_Buffer,64); putUSBUSART(USB_In_Buffer,numBytesRead); } } CDCTxService(); } -実際の応答部分は、最後の8行分のところだけです。 -こちらのソースでは、受け取ったUSBパケットをそっくりそのままWindowsに返送しています。 -なので、1フレーム時間(1mS)に複数個のパケット(64byteパケットが連続して、最後に64byte未満のパケットが来る)が送られてきてもそれをそっくりそのまま返送するので効率がよいのです。 -(もちろん、バイト指向で再組み立てする方法でも64byte未満パケットに分断さえしなければスループットは低下しません。) ~ ビルド -Pinguinoコンパイラでビルドしますが、MchipのヘッダーとMchipのUSBアプリケーションフレームワークが必要です。 *ダウンロード [#b0bc3853] -[[cdcscope.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcscope.zip]] ~ -このcdcscope.zipで生成されるHEXファイルはBOOTLOADERからの書き込みとPicKit2からの書き込みの両方に対応しています。 -こういうふうになっています。 BFC0_0000+---------------+ | Jmp _start | <=== RESETで最初に実行される命令 | | | | |BOOTLOADERの一部| +---------------+ 9D00_0000+---------------+ | BOOTLOADER | BOOTLOADERに重なっている部分はアプリでは使用しません。 | | | | | | 9D00_2000+---------------+ (_reset) | Jmp _start | <=== BOOTLOADERからの起動により最初に実行される命令 | ============= | | 割り込みVECTOR| | ============= | |_start:初期化部| | | | アプリ本体 | | | 9D00_7FFF+---------------+ -BFC0_0000からの16バイトだけが、BOOTLOADERとアプリケーションで重複しますが、 -BOOTLOADERは9D00_2000〜9D00_7FFFの範囲内のみイレース、書き換えを行ない、それ以外の領域のHEXレコードを無視しますので、スタンドアローン、ブートローダー起動のどちらでも正しく起動します。 ~ ~ ~ ~ *ベンチマーク結果 [#q0f43147] E:\cdcscope>w32term -c50 -t Entering Benchmark: Escape=^A .......................................................................................... .......................................................................................... ...................................................................... Benchmark end. 32000 bytes/141 ms, 226950 bytes/s (2269500 bps) E:\cdcscope> -スループットは毎秒226kB (実効ボーレートで2.26M BPS)になりました。 ~ ~ ~ ------------- *USB - シリアル変換器 (Serial Emulator) を作る。 [#jcf74f3e] -FTDI FT232RのようなUSB-シリアル変換器を作成します。 -これは、MicroChipのUSBフレームワークのCDC Serial EmulatorをビルドすればOKです。 -MX220F032B用に移植したものを用意しました。 ''ダウンロード'' -[[cdcserial.zip:http://psp.dip.jp/web/upload.cgi/PIC/cdcserial.zip]] -ブートローダー起動、PicKit2ライター直接書き込みの両対応HEXになっています。 -Pinguinoのmips-gccとコマンドライン版Make(Pinguino付属)でビルドします。 ~ *移植の手順についての説明 [#gbc2be36] (1)チップ品種の変換 -HardwareProfile.h というヘッダーが各品種ごとのヘッダーを選択的にincludeするようになっていますので、 HardwareProfile_MX220F032B.h というヘッダーを用意して、それをインクルードするように書き換えます。 -HardwareProfile_MX220F032B.hヘッダーにはMX220F032Bの自作基板にあわせたピン配置の定義を書きます。 ~ (2)crt0.Sの用意 -メモリー配置をブートローダー起動、PicKit2ライター直接書き込みの両対応にするためと、メモリー節約のために、少し改造したcrt0.Sを用意しています。 -これは、ramfuncのコピーを省略してサイズを0x180 byte以下に抑え、割り込みベクターの手前に収まるサイズにしたものです。 -ついでに、割り込みベクターから、割り込みハンドラーへのJmp命令も書き足しています。 ~ (3)MakefileとObjs.makの用意。 -Objs.makはリンクしたいモジュールを列挙したものです。 ~ (4)main.cの改造 -MchipのサンプルコードはPIC18FやLowPinCountPIC,PIC24F,dsPIC33など数多くの品種をカバーしているために、#ifdef〜#endifの嵐になっています。 -これでは、あまりに見通しが悪いので、PIC32MX以外の記述は思い切って削除します。 -つぎに、main()関数の先頭、かつ割り込みベクター設定があればその直後にそれを上書きする形で下記の記述を追加します。 _CP0_SET_EBASE(_RESET_ADDR); // 割り込みベクターを9D00_2000 に変更する. - _RESET_ADDR はリンカースクリプトから供給されるシンボルラベルです。 -最後に、USBをポーリング実装でコンパイルするときに消滅する関数_USB1Interrupt()を補うための記述を入れます。 #if defined(USB_POLLING) // for crt0.S vector dummy; // Dummy Function (Never Called) // void __attribute__((interrupt,nomips16,noinline)) _USB1Interrupt(){} #endif -これはcrt0.SからJmp命令で飛んでくる関数ですが、ポーリングモードでは実在しませんので、ダミーとしてここに置きます。実際には割り込みませんのでここに飛んでくることはないです。 -(crt0.Sを毎回書き換えるのが面倒なのでCレベルで対処)
テキスト整形のルールを表示する
ログインまたはアカウント作成