圏9研究所 工作室

圏9研究所の開発情報資料など

STM32F411 BlackPill USB Speaker(5)USB接続ダウン対策

ホストとの接続が不安定なため対策しておきます

1. USB接続ダウン発生状況と対策
1)USB接続ダウン状況
(1)発生状況
 発生するのは
 ・USBコネクタ接続直後 USBリセット解除から80msec後付近
 ・再生停止
 ・ホスト側でのスピーカー選択解除
 概ね50%の確率でダウンするがリトライすれば連続3回程度を限度にして正常に接続される

(2)発生後の状態
 ホスト側  変化なし 出力デバイスとしての認識は解除さずデータも送信する
 デバイス側 機能停止 以後オーディオデータをバッファに送らない

2)ダウン検出処理
(1)割込フラグと処理
 USB処理はすべてUSB割込内で処理されているので割込処理を解析
 処理関数: HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) <stm32f4xx_hal_pcd.c>

割込回

割込フラグ

処理

1

USB_OTG_GINTSTS_PXFR_INCOMPISOOUT

= OTG_FS_GINTSTS Bit21 INCOMPISOOUT:

    Incomplete isochronous OUT transfer

INCOMPISOOUT割込で

is_iso_incomplete = 1U

  hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;  //epnum=1

2

USB_OTG_GINTSTS_OEPINT

= OTG_FS_GINTSTS Bit19 OEPINT:

    OUTendpointinterrupt

OEPINT割込で

is_iso_incomplete == 1U の場合

USBD_AUDIO_IsoOutIncomplete() <usbd_audio.c>が呼ばれる

 

3)ダウン対策
  USBD_AUDIO_IsoOutIncomplete()  に何も書かれていないのでお手本を参考にコードを追記
(1)お手本のコード USBD_AUDIO_IsoOutIncomplete()    <usbd_audio.c>

/**
  * @brief  USBD_AUDIO_IsoOutIncomplete
  *         handle data ISO OUT Incomplete event
  * @param  pdev: device instance
  * @param  epnum: endpoint index
  * @retval status
  */
// Fix suggested by Andrew to restart audio (fix Windows problem ?)
static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef* pdev, uint8_t epnum) {
	UNUSED(epnum);
	USBD_AUDIO_HandleTypeDef *haudio;
	haudio = (USBD_AUDIO_HandleTypeDef*)pdev->pClassData;

	USBD_LL_FlushEP(pdev, AUDIO_OUT_EP);

	/* Prepare Out endpoint to receive next audio packet */
	(void)USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, (uint8_t *)&haudio->buffer[haudio->wr_ptr], AUDIO_OUT_PACKET_24B);

	return (uint8_t)USBD_OK;
}

 

(2)実装コード  USBD_AUDIO_IsoOutIncomplete()    <usbd_audio.c> 

static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
  //UNUSED(pdev);
  UNUSED(epnum);

  // Fix suggested by Andrew to restart audio (fix Windows problem ?)
	USBD_AUDIO_HandleTypeDef *haudio;
  	haudio = (USBD_AUDIO_HandleTypeDef*)pdev->pClassData;

  	USBD_LL_FlushEP(pdev, AUDIO_OUT_EP);

  	/* Prepare Out endpoint to receive next audio packet */
  	(void)USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, &haudio->buffer[haudio->wr_ptr], AUDIO_OUT_PACKET);

  	return (uint8_t)USBD_OK;
}

 

2.コンパイル最適化
 最適化すると動かない
 C/C++ Build : Setting : MCU GCC Compiler : Optimization : Optimization level    None(-O0) に設定

3.おまけ  
 おまけとして適切な対策が見つかるまでに使っていたリトライコードを参考に記載
(1)おまけリトライ
 USBソフトコネクト + CPUリセット
  USB接続ダウンを検出したら
  ・USB D+ ポートに L 出力
  ・10ms 以上WAIT
  ・CPUシステムリセット

(2)コード

#define RESTART_USB 	do{GPIO_InitTypeDef GPIO_InitStruct = {GPIO_PIN_12, GPIO_MODE_OUTPUT_PP};\
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);\
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);}while(0)

	RESTART_USB;
	HAL_Delay(12);
	HAL_NVIC_SystemReset();

 

おまけコードのお手本

community.st.com

 

4.解説
1)発生原因について
・原因不明
・処理している割込フラグからアイソクロナス通信に関するエラーのようですがアイソクロナスはDisableになっている
 アイソクロナス転送でのEVEN/ODD問題と同じように思われる
・USBパケットを追うと接続ダウン発生までの内容は発生有無にかかわらす同じように見える
・デバイス側のハードとホスト側の処理(OSや個体差)も絡むので原因究明は程々にしてお手本のコードを有難く使わせて頂いて対応

2)おまけのコード
・この件を対策しておかないと先へ進めなかったのでとりあえずの対策
 USBソフトコネクトは他でも有効に使える
・おまけお手本の待ち時間は500msecになっていますがUSBの規格は10msec以上なので12msecに設定
 WAIT設定値が適切かどうか不明であるが動く

次はオーディオデータの転送処理について