3

stm32f4xx uC で C の組み込みプロジェクトに取り組んでいます。

ループ操作 XYZ を連続して実行するコードの一部があり、時々 TIM4 割り込みがいくつかのグローバル パラメータを変更し、操作 XYZ を再開させます。

コードは次のようなものです。

for (;;) {
       //line A
    XYZ;
       //line B
}

XYZ は、バッファとその他の間のデータ転送を含む複雑な操作です。

TIM4 割り込みハンドラはこれを行います: XYZ を停止し、XYZ 操作に影響するいくつかのグローバルを変更します。

したがって、基本的には、XYZ を繰り返し実行し、TIM4 割り込みで XYZ を停止し、パラメータを変更してから、新しいグローバル パラメータで XYZ を再起動してループを再開する必要があります。

問題: XYZ には多くの命令があるため、TIM4 IRQ がその途中で発生する可能性があり、IRQHandler がグローバルを変更した後、XYZ の途中から操作が再開され、プログラムが台無しになります。

の最初の解決策: __disable_irq() で行 A の割り込みを無効にし、__enable_irq() で行 B でそれらを復元します。

XYZ 複合操作は他の割り込み (TIM4 以外) を使用する必要があるため、失敗します。

の解決策 次のコマンドを使用して、ライン A の TIM4 割り込みのみを無効にします。

TIM_ITConfig(TIM4, TIM_IT_Update , DISABLE) 

次のコマンドを使用して、B行で有効に戻します。

TIM_ITConfig(TIM4, TIM_IT_Update , ENABLE)

割り込みを失っているため失敗します。int が復元されると、XYZ 中に到着した割り込みは無視されます。これは大きな問題です (理由の 1 つは、TIM4 IRQHandler がグローバルを変更し、TIM4 を再度アクティブにして後で割り込みを発生させることです。割り込み間の期間が異なるため、私はこれを行います)。

誰でもこの問題の解決策を教えてもらえますか? TIM4 IRQ を無効化/復元し、割り込みを失わないようにするより良い方法はありますか?

4

5 に答える 5

1

XYZ の処理が完了したら、グローバル変数のコピーを操作して、割り込みから新しい値をスワップすることができます。

グローバルが変更されたときに XYZ の処理を​​すぐに停止する必要があるかどうか、または XYZ が処理を終了して変数の新しいコピーにスワップするまで待つことができるかどうかは、質問からは明らかではありません。XYZ の処理から抜け出す必要があると仮定して操作しますが、抜け出すのは簡単です。

コードは次のようになります。

volatile int x;
int x_prime;

int main(void)
{
    while(1)
    {
        //copy in new global parameter value
        x_prime = x;

        while(1)
        {
            //do stuff with x_prime
            if (x_prime != x)
            {
                break;
            }

            //do more stuff with x_prime
            if (x_prime != x)
            {
                break;
            }
        }
    }
}

// interrupt handler
void TIM_IT_Update(void)
{
    x++;
}

パターンは、break変更していないことを前提としていますx_prime。を変更する必要がある場合x_primeは、別のコピーが必要になります。

割り込みが無効になることはないため、割り込みを失う心配はありません。また、割り込みによって変更されたパラメーターのコピーを操作しているため、コピーを作成するまでこれらの値を確認していないため、割り込みが実行中にパラメーターを変更しても問題ありません。

于 2012-12-11T13:37:55.383 に答える
1

潜在的に利用可能なオプションがいくつかあります (私は ARM アーキテクチャを 100% 使用しているわけではありません)。

  • 割り込み優先度/レベル マスク レジスタを変更して、TIM4 のみをマスクし、他の割り込みが発生するようにします。うまくいけば、TIM4 がマスクされた状態で起動された場合、レベル マスクの復元時に ISR を記憶して起動します。
  • 割り込みをマスクし、XYZ 中に設定されている TIM4 割り込みフラグを手動でチェックします。
  • XYZ を小さなセクションに分割し、絶対に必要な場合にのみ TIM4 をマスクします。
  • データのコピーを操作し、オプションで TIM4 割り込みフラグをチェックして、結果を続行/保持するか、破棄して再起動するかを決定します。
  • 時間を確認し、TIM4 がすぐに起動する可能性がある場合は XYZ を開始しないようにするか、TIM4 が起動した後に XYZ を N 回だけ実行します。
于 2012-12-11T14:47:40.643 に答える
1

処理に中断期間よりも長い時間がかかる可能性がある同様の状況に陥った場合、FIFO を使用して受信データから処理を分離します。IE: TIM4 は FIFO を満たします。XYZ (またはマネージャ) が FIFO を消費し、データを処理します。

(グローバルを使用してデータやプロセス フローを制御するべきではないため、設計が間違っている可能性があると思います。この問題に関する研究のための参考書: Making Embedded Systems: Design Patterns for Great Software)

于 2013-03-11T14:47:49.027 に答える