2024年6月26日水曜日

STM32 CDC(Virtual COM port)がwindowsで認識されない件(RTOSも)

STM32F401のCDC(Virtual COM port)を動かそうとしています.でも動かなくて丸一日浪費しました.

不具合:windows10のデバマネがSTM32 CDCを認識しない
どんな風に認識しないのかというと、、、USB cableがPCに挿されたことをwin10は認識している.しかしSTRING discriptorだけを読めてない.win10が読みに行ってないというのが正解かもしれない.(USB device tree viewerで観測)

なお、CDCのsource codeはSTM32CubeMXで生成しており、生成した直後のprojectをビルド→焼きしただけ.正常ならこれでwin10が認識するはず.VBUSは使ってません.

認識する/しないについていろいろな条件があります.
1)Linuxに接続すると正常に認識される (lsusb -v)
2)Linuxに接続後、USB cableをwin10に繋ぐと正常に認識される(resetするとダメになる)
3)2ヶ月ぐらい前にSTM32CubeIDEで生成した少々複雑なprojectは正常にwin10が認識する
4)1と3のsource fileを差分チェックしたがdiscriptor等は同じ

以上の条件により仮説は、、、
起動シーケンスにおける②と③と④のtimingじゃないだろうか? つまり、起動直後はSTM32の何かが寝ボケている説.例えばSysTickがまだ動き始めていないみたいなのを疑う.
 ①STM32F401の起動
  →②各種peripheral初期化
   →③USB CDC起動
    →④descriptorのやり取り
     →⑤失敗

治りました
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  HAL_Delay(3000);
  while (1) {  }
場所はmain()の先頭の方で初期化してるところです.USB初期化の直後にdelayを入れる.これだけで治りました.これで治ってしまうのもおかしな話ですけどね.

ちなみにHAL_Delay()の中はこんな事をやっていて、HAL_GetTick()を呼ぶと喝が入るんじゃないかな? Tickは1mSecです.
HAL_Delay(uint32_t Delay) {
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay){}
}

疲れました.丸一日損した.

ーーーー
RTOSと組み合わせるとまたトラブル.症状は同じです.

どーせUSB初期化の問題でしょう.RTOSだとUSB初期化する場所が変わりまして、default taskでやるように自動生成されます.これにosDelay()やHAL_Delay()を追加しても治りませんでした.
void StartDefaultTask() {
  MX_USB_DEVICE_Init();
  for(;;)  {
    osDelay(1);
  }
}

そこで、default taskからMX_USB_DEVICE_Init()を撤去します.
main()の始まり付近のperipheral初期化の場所に移動し、delayを追加します.
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_SPI3_Init();
  /* USER CODE BEGIN 2 */
  MX_USB_DEVICE_Init();
  HAL_Delay(3000);
  /* USER CODE END 2 */

これでRTOSでも動くようになりました.一体何が起きてるんだか?

かしこ

13 件のコメント:

  1. >一体何が起きてるんだか?
    そのチップは、
    ・中華製の、精巧なニセモノ
    だったりしませんよね・・・?
    ※マスクパターンをパクる時に、「微妙にサイズが変わって」配線長が変化して、
    「動特性」が、変わってたりして。

    返信削除
    返信
    1. STM32F103xxxはパチモンだらけのようです.わたしも被害を受けました.
      同F401xxxのパチモン情報は聞いてません.真相は????

      削除
    2. なんか、以前に言ってた、
      ・RTOS が動かない
      に、状況が似ているような・・・
      ※一寸先は闇

      削除
    3. >以前に言ってた、
      「32F103xxxのパチモン」の時の件です

      削除
    4. あれは阿鼻叫喚の地獄絵図でした...

      あの基板は封印してありんす

      削除
  2. murasaki
    いろいろと近代化されて、こういうおまじな系は20世紀で無くなったかと思っていましたが、まだ現役なんてすねー。
    昔は初期化処理にたくさんおまじないが書いてあったような気がします。謎のwaitルーブもあちこちに。
    しかもパソコンで漢字が使えない時代だったので、ローマ字で意味の読み取れないコメントが少しだけ書いてあって。SAKUJOKINSHIとか。

    返信削除
    返信
    1. 箱根Nerfのマギにも裏コードがたくさん貼ってありました.

      USBの接続信頼性はLinuxの方がwinより良い気がします.
      USB cableを挿してからデバドラが認識するまでの所要時間が、
       Linux 遅い
       Win 素早い
      ような感触なので、Winのテンポについて行けないdeviceがあるんじゃないかとゆう仮説です.なのでUSB認識の問題が生じたらいつもLinuxで調べるんですが今回もそうゆうのでした.

      削除
    2. >USBの接続信頼性
      基本的に、USBは、設計思想が、
      ・ハード最小、ソフトで何でもやる
      という思想なので、例えば、
      ・CPUが貧弱だと認識しなかったり、処理が遅れる
      ・マルチタスクで「CPUが、他の仕事で忙しいと」上手く動かない
      とかあったりします。
      ※それでも「Linuxのほうがマシ」というのは、恐らく、Linuxのほうが、Windows よりも、
      ・core に近い部分で処理されてる
      からだと思います。最近のWindowsは特に、デバドラ系は、
      ・階層が深く/複雑になりすぎている
      ので、「なかなか」ドライバの処理までやってこない、感じがします。

      ちなみに、↑で
      ・Windows よりも Linux のほうが、USB を認識しやすい
      って書いてますけど、私の印象は逆なんですけどねぇ・・・
      Windows 11 使ってますが、(モノには依りますが)USBって、刺してから、
      ・忘れた頃に認識してる
      感じがします。同じモノなら、Lunix のほうが、早く認識する感じ。

      削除
    3. まだたまに起動直後に認識しなくて何度かresetしたりしてます.
      USB INITの前後にwait入れると百発百中になったかなぁってとこ.くそぉ
      MX_GPIO_Init();
      HAL_Delay(3000);   ←これと
      MX_USB_DEVICE_Init();
      HAL_Delay(3000);   ←これ

      削除
    4. >USB INITの前後にwait入れる
      これは全くその通りのハズで、USBの認識って、基本的に、
      ・polling 処理
      なので、要するに「どこぞのタイマーで、定期的に見に行ってる」形なので、そっちのタイマー割込みよりも「優先順位が高い処理」が、先に処理されてると、
      ・何時まで経っても、認識しない
      事態に陥ります。(この辺は、OSの「マルチタスク処理の出来」に、依存してるところがある。この辺は、Windows よりも Linux のほうが、一般的に出来が良いといわれてます。)

      削除
    5. 割り込み優先度は気になるところです.
      USB packetレベルの割り込みまではライブラリを見れてないです.
      もう少し上位のtransfer/recieveのcallbackを使ってるかんじで.
      よろず開発はLinuxが好きです.

      削除
  3. 読者 納期厳守 コミケは入稿1ケ月前7/12が締め切り がんばれ コミケ行く人
    進捗を報告せよ やっぱり締め切りが迫らないとねえ
    いままで1月から半年あったではないか わかっちゃいるんですが
    そんなことをやっている場合か  ・・・・
    もっとやるべきことがあるだろう ・・・・
    そうだ 日曜日は 協会へ行こう
    なにしにいく 讃美歌の13番を
    おわっとる・・ そして
    あの時やっておけばと 徹夜中に思い出すのであった 反省がいかされていない 自分

    返信削除
    返信
    1. まーだまだ1ヶ月半もありますから余裕の余裕

      削除