3

* アップデート *

これが私が見つけたものです。その関数がそこにあるときはいつでも、実際にコードがロックされることはありません。実際には、RTC I²C 関数の読み取りが非常に遅くなりますが、コードは適切に実行されますが、RTC を読み取るたびに、通過するまで非常に長い時間待たなければなりませんでした。

そのため、RTC のアラーム割り込みがあり、これが ISR 内の他の I²C 相互作用をトリガーしていたため、2 つの I²C 通信を同時に実行しようとしていたようで、プロセスが遅くなりました。ISR の機能を削除しましたが、現在は機能しています。引き続き調査していきます。


IAR 5.40 を使用して STM32F103 マイクロコントローラをプログラミングしているときに、この問題が発生しています。ローカル変数を printf しようとすると、問題の関数に到達する前に別の時点でコードがフリーズするというこの関数があります。

これを引き起こしている可能性があるのは何ですか?

これは機能です:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string

  printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!

  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

私もこれを試しましたが、これは私が経験したロックを引き起こしません:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10);
  printf("index = 2\n");


  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

最適化がまったく有効になっておらず、I²C RTC からバイトを読み込もうとするとコードが動かなくなりますが、これを削除するprintf("index = %s\n", bTmpSms);か、代わりにこれを使用するとすぐにprintf("index = 2\n"); 、すべてがうまくいきます。何か案は?

bSmsIndex が実際には 30 を超えることはありません。その場合でも、この関数が呼び出される前にロックが発生します。

4

7 に答える 7

2

char bTmpSms[3]「99」のスペースしかありません。bSmsIndex が 100 以上の場合、自分のものではないメモリに書き込もうとしています。


アップデート後に編集

itoa私のローカルマシンには参照がありませんが、これを見つけました ( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ )。その参照によると、宛先配列は、可能な値に対して十分な長さでなければなりません。ドキュメントを確認してください。仕様itoaは異なる場合があります。

またはsprintf、 、snprintf、または標準で記述されている関数を使用します。

于 2010-10-12T18:35:42.670 に答える
1

変数bTmpSmsを何かに初期化しないと、問題が発生するようです。

また、問題となっているのはprintfではないことにも気づきました。itoa関数です。それが問題だとは思わなかったのに、itoa関数にコメントすると、コード全体が機能することを確認することができました。

だから私はこれをすることになった:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[4] = "aaa";    // I still need to find out why this is !!!

  itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string

  printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!

  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

これは私が得たitoa関数です:

char itoa(int value, char* result, int base)
{
  // Check that the base if valid
  if (base < 2 || base > 36) {
      *result = '\0';
      return 0;
  }

  char* ptr = result, *ptr1 = result, tmp_char;
  int tmp_value;

  do
  {
    tmp_value = value;
    value /= base;
    *ptr++ = "zyxwvutsr

qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz "[35 +(tmp_value --value * base)];} while(value);

  // Apply negative sign
  if (tmp_value < 0)
      *ptr++ = '-';
  *ptr-- = '\0';
  while(ptr1 < ptr)
  {
    tmp_char = *ptr;
    *ptr--= *ptr1;
    *ptr1++ = tmp_char;
  }
  return 1;
}
于 2010-10-12T20:29:50.273 に答える
1

いくつかのアイデア:

が文字列を適切に NUL で終了していない場合itoa()、printf を呼び出すと、マシンが NUL を永遠に探す結果になる可能性があります。

pmg には非常に良い点があります。

また、最初の引数がどの型であるかを考慮してitoa()ください。署名されていて、符号なしの整数を渡す場合、bTmpSms で予期しないマイナス記号が表示される可能性があります。sprintf()代わりに使用してみてください。

于 2010-10-12T18:39:51.777 に答える
1

コードの変更により、残りのコードがメモリ内で移動されます。私の推測では、ここに記載されていないコードの他の部分がランダムな場所を攻撃していると思われます。最初のケースでは場所に重要なものが含まれていますが、2 番目のケースでは含まれていません。

これらは、追跡するのが最も困難な種類の問題です*。幸運を。

*最悪ではないかもしれません - 複数のスレッド間の競合状態が 1 週間に 1 回しか現れない場合は、さらに悪化する可能性があります。まだ私の好きな種類のバグではありません。

于 2010-10-12T20:20:50.820 に答える
0

2index = vs.index =でこの領域を分解してみてください%s

于 2010-10-12T19:56:29.037 に答える
0

bSmsIndex の値は?

99 を超えると文字列に変換すると 3 桁になります。ゼロで終わると 4 文字になりますが、bTmpSms に 3 文字しか割り当てていないため、null が上書きされる可能性があり、printf は次の null まで bTmpSms の後にあるものを出力しようとします。それは本当に何にでもアクセスできます。

于 2010-10-12T18:37:51.810 に答える
0

bSmsIndexあなたが印刷しようとしている価値は何ですか?

99 より大きい場合は、bTmpSms配列をオーバーランしています。

それでも問題が解決しない場合は、IAR の非常に優れたデバッガーを使用してください。アセンブリ ウィンドウのprintf()が呼び出されている場所にドロップし、問題が解決するまで 1 ステップずつ実行します。それはおそらく問題が何であるかを明らかにするでしょう。

または、簡単なトラブルシューティングとして、アレイのサイズを大きく (おそらく 8) にしてみて、何が起こるかを確認してください。

于 2010-10-12T18:38:12.463 に答える