USB通信について
USB(Universal Serial Bus)の目的
パソコンに接続されている周辺機器インターフェースを統合していくこと。
USBは、PnP(プラグ&プレイ)機能がある。
コネクタの着脱により、自動的にデバイス接続/切り離し処理が行われる。
デバイスが接続されたか否かは、各ハブの部分で検出される。
ホストがハブをチェックしに行ったとき、検出する。
ハブを多段に接続することで、一つのUSBポートに多数のデバイスが接続できる。
USBは、ハブは5段まで。
USBは、各デバイスにアドレスを割り振る。
アドレス・ビット長は7ビット
接続出来るデバイスは最大127台。
USBの転送は、ホストがターゲットをポーリングし、ターゲットが応答する形で行われる。
多数のターゲットが接続し、応答を待っていると、遅すぎてバスが渋滞してしまう。
データ転送も、データ転送を受け取れたか否かをターゲットのCPUが応答するまでは待てない。
上記問題を解決する方法として、エンドポイントという概念がある。
エンドポイント:
通常は、ネットワークに繋がっている、PCやサーバ、スマホなど端末のこと。
ここでいうエンドポイントは、通信端点のこと。
参考:
USBコントローラにエンドポイントを複数持つことにより、ソフトウェアは、複数の通信経路として
認識することが出来るようになる。
FIFOバッファ・メモリ
参考記事:
サスペンドとは
Windowsの省電力機能の一つで、長時間使用されていないUSB機器への電力供給を停止するもの。
Windows の初期設定時、電力の消耗を抑えるため、
一定時間使用していない USBポートは自動的に電源が切れるように設定されている。
「 USB のセレクティブサスペンドの設定 」 を無効にすることで、一定時間経過後も USB機器の電源が切れないように設定することができます。
レジュームとは
レジュームとは、コンピュータの実行状態を保存して停止させ、次に使用するとき即座に停止直前の状態に復帰する機能。
特に、停止状態から操作可能な状態に復元する動作のこと。
サスペンド処理
STM32Cube HALライブラリを使用してUSBの一時停止(Suspend)コールバック関数を実装しています。
code:c
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{
/* Inform USB library that core enters in suspend Mode. */
USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/* Enter in STOP mode. */
/* USER CODE BEGIN 2 */
if (hpcd->Init.low_power_enable)
{
/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register */
SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
}
UsbApi_Suspend();
/* USER CODE END 2 */
}
/** ************************************************************** */
/**
* サスペンド処理
* @param void : None
* @return void : None
*/
/** ************************************************************** */
void UsbApi_Suspend( void )
{
GUsbCtrlInf.bUsbCnct = (bool)false; ///<USB未接続状態
UsbApi_ChgConnectState( (bool)false ); ///<USB接続状態変更(未接続)
}
/** ************************************************************** */
/**
* USB接続状態変更
* @param bCnct : true=接続/false=未接続
* @return void : None
*/
/** ************************************************************** */
void UsbApi_ChgConnectState( bool bCnct )
{
UCHAR ucIntSts; ///<割込み許可/禁止状態
/** 接続時 *************************************************** */
if ( bCnct == true ) { ///<接続?
/** USB送受信バッファ情報の初期化 ************************** */
UsbTxBuff_InitInf(); ///<USB送信バッファ情報の初期化
UsbRxBuff_InitInf(); ///<USB受信バッファ情報の初期化
}
/** 割込み禁止 *********************************************** */
ucIntSts = __disable_irq2(); ///<割込み禁止
/** 接続時 *************************************************** */
if ( bCnct == true ) { ///<接続?
GUsbCtrlInf.bUsbCnct = true; ///<USB接続フラグON
GUsbCtrlInf.bUsbNewCnct = true; ///<USB新規接続フラグON
GUsbCtrlInf.usSendResetTim = USBTIMER_SENDNONE; ///<送信リセットタイマ=更新なし
GUsbCtrlInf.eTxSt = USB_TX_ST_IDLE; ///<USB送信ステート=IDLE
GUsbCtrlInf.usEsofCnt = 0; ///<ESOFカウンタをクリア
HAL_TIM_Base_Start_IT(&htim13); ///<タイマースタート
}
/** 未接続時 ************************************************* */
else { ///<未接続!!
GUsbCtrlInf.bUsbCnct = false; ///<USB接続フラグOFF
GUsbCtrlInf.bOpenComm = false; ///<COMMオープンフラグOFF
GUsbCtrlInf.bReConnecting = false; ///<USB再接続中フラグOFF
// GUsbCtrlInf.bReConnecting = true; ///<USB再接続中フラグON
GUsbCtrlInf.usReCnctTim = USB_RECONNECT_TIM; ///<USB再接続タイマを設定
GUsbCtrlInf.usSendResetTim = USBTIMER_SENDNONE; ///<送信リセットタイマ=更新なし
// USBSEL( OFF ); ///<USB-OFF(USBデータライン切断)
GUsbCtrlInf.eTxSt = USB_TX_ST_IDLE; ///<USB送信ステート=IDLE
HAL_TIM_Base_Stop_IT(&htim13); ///<タイマーストップ
}
/** 割込み許可 *********************************************** */
if ( ucIntSts == 0 ) { ///<割込み許可?
__enable_irq(); ///<割込み許可状態に戻す
}
}