STM32 USB VCPバグ


8

私は過去2週間プロジェクトに取り組んでおり、この1つの問題のデバッグにこの1週間かかりました。誰かが助けてくれるかどうか疑問に思って、私はできるだけ明確で明確になるように努めます。

STM32F302K8(Cortex M4)に基づくマイクロコントローラーにUSB仮想通信ポートを実装しようとしています。STM32CubMXを使用して、CDCクラスを実装するUSB​​フルスピードデバイスをセットアップするために必要なコードを生成しました。デバイスがWindows(デバイスマネージャー)とLinuxの両方に表示されます。サンプルコードに基づいて単純なエコー関数を実装できますが、関数USBD_CDC_SetTxBufferを使用してPCにデータを送信しようとすると、ハードフォールトハンドラーが起動します。USBD_CDC_Init()がUSBデバイスの初期化で呼び出されないため、UsbDeviceFS.pClass(USBD_CDC_SetTxBufferで必要)フィールドが初期化されないという事実にこれを絞り込みました。

STフォーラムに記載されているサンプルコードのいくつかのバグ(ヒープサイズの変更、USBD_CDC_TransmitPacketの送信フラグの修正、CDC_DATA_HS_MAX_PACKET_SIZEのサイズの256への変更など)の修正を実装しましたが、同じエラーが発生します。

デバイスのセットアップコードは

* USB Device Core handle declaration */
USBD_HandleTypeDef hUsbDeviceFS;

/* init function */                    
void MX_USB_DEVICE_Init(void)
{
  /* Init Device Library,Add Supported Class and Start the library*/
  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);

  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);

  USBD_Start(&hUsbDeviceFS);

}

最後にSTMでUSBを操作してからしばらく時間が経過しましたが、USBD_CDC_Init()がmallocを実行しようとしていると思います。問題は、デフォルトのセットアップではヒープに十分なスペースがないため、増やす必要があるということでした。
brhans 2015年

こんにちは。ヒープサイズを0x600に増やしましたが、何も起こりません。mallocを呼び出す関数は、ブレークポイントを設定すると、呼び出されないように見えるためです。
Galaxy

回答:


6

私自身の質問に答えると、問題は、コードがUSBの初期化が完了するのを待たずに、すぐにデータの送信を開始したことです。ブール値にアクティブな待機を挿入するか、遅延を追加すると(@ramezで指摘)、問題が解決します。

更新このバグは、STの後続のUSB CDCドライバーバージョンで修正されています。セットアップにHAL_Delayが追加されました。警告は、何らかの理由でSys_Tickが機能しない/非アクティブ化/まだ初期化されていない場合、コードがハングすることです。


1
はい、これを別の質問として投稿してください。この回答では、元の質問に関連する情報のみを保持してください。
m.Alin、2015

2

STM32F4検出用のコードを生成するためにCubeMXを使用しました。あなたと同じように仮想COMポートとして使用しました。USBD_CDC_SetTxBuffer()関数を直接使用しませんでした。でusbd_cdc_if.cファイルという名前の関数が存在しCDC_Transmit_FSは() 。生成されたコードにバグがあり、関数はパラメーターとしてバッファーを受け取り、それを使用して何もしませんでした。修正された機能コードは次のとおりです。

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  memcpy(UserTxBufferFS, Buf, sizeof(char) * Len);
  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);   
  result = USBD_CDC_TransmitPacket(hUsbDevice_0);
  return result;
}

実際には、memcpyをコードに追加する必要がありました。この修正後、この送信機能を使って、マイクロローラーからPCにデータを送信できました。例えば:

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  configureGPIOs();

  uint8_t Buf[] = "Test";

  HAL_Delay(1000);

  while (1)
  {
      CDC_Transmit_FS(Buf, 4);
      HAL_Delay(1000);
  }
}

MX_USB_DEVICE_Init()の初期化は、あなたと同じです。


1
ラメズありがとうございます。問題を見つけました。仮想通信ポートが初期化を完了したかどうかをテストする必要があり、CDC_Inmit_FSでブール値を使用しました。メインループがtrueになるのを待ってから、CDC_Transmit_FSを呼び出しました。コード内のHAL_DELAYでも同じ効果が得られると思います。お手伝いありがとう。
Galaxy

1

まず、hUsbDevice_0がnullかどうかを確認します(ソリューションに要素がありません)。

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

これにより、uCがハングするのを防ぎ、遅延で忙しく待つ必要がなくなります。

CDC_Transmit_FSのどこかに配置できます。

USBD_StatusTypeDef CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) {

    if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

    USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) hUsbDevice_0->pClassData;

    if (hcdc->TxState != 0)
        return USBD_BUSY;

    uint8_t result = USBD_OK;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);

    return result;
}

0

私も同じ問題を抱えていましたが、必要なことは、USB接続をコンピューターに再接続することだけでした。ほとんどの場合、コードをフラッシュしてマイクロコントローラーをリセットしますが、PC側では列挙が更新されません。 USBD_CDC_Initは、ホストがデバイスのプローブを開始したときに呼び出されます。そのため、pClassDataはNULLです。


1
ソフトウェアで再列挙を強制することもできます。カスタムドライバーがこれをより豪華な方法で処理していない場合、再接続後の2番目の最も簡単な方法は、デバイスマネージャーでポートを無効/有効にすることです
stiebrs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.