富士通 MB90F543 の成熟したプログラムで見つかったバグを修正しようとしています。このプログラムはこれまで 10 年近く動作していますが、ある特殊な状況下では、最初の 2 つのことを実行できないことが判明しました。そのうちの 1 つが重要です。
低レベルおよび高レベルの初期化 (ポート、ピン、ペリフェラル、IRQ ハンドラー) の後、構成データが EEPROM から SPI 経由で読み取られ、ステータス LED がしばらくオンになります (それらをオンにするために、データは SPI 経由で LED ドライバーに送信されます)。これらの特別な状況が最初に発生し、EEPROM の読み取りを呼び出す最初の関数だけが失敗し、さらに、点灯するはずの LED のいくつかが点灯しません。
プログラムは C で書かれており、Softune v30L32 を使用してコンパイルされています。驚くべきことに、低レベルのハードウェア init に単一の __asm(" NOP ") を追加するだけで、上記の状況でプログラムが期待どおりに動作するようになります。最適化設定で「ポインター エイリアシングの最適化を制御する」をオフにするだけで十分です。さまざまな場所に数行のコードを追加することも役立ちます。
__asm(" NOP ") を使用するバージョンと使用しないバージョンのコンパイル済みプログラムの ASM リストを比較 (DIFF) し、前述の両方のオプティマイザー設定を使用して比較しましたが、すべて問題なく表示されます。
コンパイル中に Softune コンパイラが何年も出力してきた唯一の警告は次のとおりです。
*** W1372L: セクションが RAM 領域または I/O 領域 (IOXTND) の外に配置されています
かなり一般的な質問だと思いますが、より大きな画像を持っている人が考えられる原因を指摘できるかもしれません.
何がそのような奇妙な動作を引き起こす可能性があるか考えていますか? バグを見つけて修正する方法
初期化中に、いくつかの長い (約 20ms) 遅延ループが使用されます。それらは約 2ms から増加されましたが、役に立ちませんが、ハードウェア初期化関数の任意の行で単一の NOP が機能し、関数の前後でも役立ちます。
両方の待機ループが機能します。オシロスコープで確認してみました。(LED のオンとオフを追加しました)。
SPI クロックを 1MHz から 500kHz に落として、タイミング仮説を確認しました。何も変わりません。250kHz まで減速すると、コードの一部の実行時間が長すぎる (>25ms) ため、ウォッチドッグがリセットされます。
もう一つ。ソースファイルにローカル変数を追加すると、問題が消えたり再発したりすることがあります。同じことが、初期化されていないローカル変数の初期化にも当てはまります。いずれかのファイルに数行のコードを追加すると、問題が解決したり明らかになったりします。
void main(void)
{
watchdog_init();
// waiting for power supply to stabilize
wait; // about 45ms
hardware_init();
clear_watchdog();
application_init();
clear_watchdog();
wait; // about 20ms
test_LED();
{...}
}
void hardware_init (void)
{
__asm("NOP"); // how it comes it helps? - it may be in any line of the function
io_init(); // ports initialization
clk_init();
timer_init();
adc_init();
spi_init();
LED_init();
spi_start();
key_driver_init();
can_init();
irq_init(); // set IRQ priorities and global IRQ enable
}