0

富士通 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
}
4

2 に答える 2

0

多くのことの1つかもしれませんが、2つ思い浮かびます。

タイミング。

電源が安定するのに十分な待機時間がなく、すべてがクロックに同期されていない可能性があります。NOP はすべてを同期に戻します。

アライメント。

おそらく NOP は、ハードウェアが期待する 32 ビットまたは 64 ビットの境界に合わせて命令を整列させます。(IO 操作ではダブル ワード境界にあることがしばしば予想されるため、メインフレーム アセンブラでこれを頻繁に行っていました)。

于 2015-01-29T02:02:25.430 に答える
0

問題は解決しました。些細なバグが原因でした。

EEPROM の nHOLD および nCS 信号は、MCU のリセット直後ではなく、EEPROM を最初に使用する前に初期化されました。その結果、それらは 0 で、非常にアクティブでした。これは、EEPROM が選択されましたが、保留中であることを意味します。その間、SPI を使用したその他の転送が開始されました。8 つの CLK パルスのうち 6 つ後、EEPROM の nHOLD I/O ピンが初期化されてハイになりました。EEPROM は保留状態ではなくなったため、他の周辺機器のデータの最後の 2 ビットをクロックインしました。EEPROM に対するその後のすべての操作で、CLK と MOSI が同期していないことがわかりました。

NOP などを追加すると、nHOLD 0->1 エッジの瞬間が最後の CLK パルスの後に発生するようにシフトされました。これで CLK-MOSI が同期しました。

MCU のリセット直後に、すべての EEPROM の SPI ライン、特に nHOLD と nCS を初期化するだけで済みました。

于 2015-06-20T21:30:12.580 に答える