Flash書き込み後のDSPプログラムの動作が異常な場合の分析


この間、DSP 6713のFlash書き込みをデバッグしていましたが、今ではFlashの書き込みも心の中にあります.
その日、非常Happyの発见でフラッシュLEDをFlashに书き込み成功し、そして、すべてOKだと思った……
その日、300 KB以上のプログラムを成功裏に書いて、また、今回はOKだと思っていたのですが・・・
その日、Timer割り込みプログラムを書いて、Flashまで焼いたのに、ハングアップして・・・
その日、RAM上でスムーズに動作するアルゴリズム(アルゴリズムでCCSのatan関数が呼び出された)が、Flashに書き込まれた後にアルゴリズムがハングアップした・・・
その日、私は考え始めました:どんな状況がRAMの中でとてもHappyのプログラムを走ったのか、Flashに書いてこのように運行している--多くの囧相.
「実行して大切にする」というように、バグを発見する機会を大切にします.そのため、RAMで正常に動作し、Flashに書き込んでから正常に動作しない場合についてまとめます.
割り込みベクトルテーブルを確認してください
割り込みベクトルテーブルには割り込みのすべてのエントリが含まれており、Flashを書き込むときに割り込みが正常に動作することを保証する2つの方法があります.具体的には、TMS 320 C 6713焼写Flashの一般的な方法の第5節を参照してください.
プログラムに隠されているメモリエラーを確認してください
多くの場合、配列が境界を越えた場合、RAM内のプログラムは正常に動作するが、Flashを焼いた後に実行するとハングアップやプログラムが飛ぶ現象が発生する.
配列を定義したり
int x[5];

x[5]=10のような文を使うと、RAMプログラムで正しく動作する場合があり、PCでも可能であるはずです.しかし、このプログラムをFlashに書き込んでから実行し、DSPは思い切ってバイバイと言います!
したがって、プログラムコードの配列境界とポインタ操作を慎重にチェックしてください.DSPプログラムでは,Cライブラリ関数のmalloc関数は絶対に使用しない.メモリを動的に割り当てる操作が必要な場合は、自分で1つ書くか、uCOS IIやDSP/BIOSなどの組み込みオペレーティングシステムを使用します.
mathの使用はできるだけ避けてください.hにおける三角及びlog等の関数
何が原因なのか分からないし、atan関数の使い方が正しくないせいかもしれない.私の最初のプログラムではatan(x)を直接計算しました
float x,y;
...
y = atan(x); // x   [0, 1.7]

RAMでもPCでも何度もテストして問題はありません.
Flashを書き込んだ後も、ハングアップではありませんが、プログラムがatanという関数に実行されると長い間カードに引っかかり、次のように実行されます.
まさかmath.h中のatan演算効率が低すぎる?しかし、なぜRAMで実行できるのでしょうか.これはまだ分かりません.
そこで,三角関数やlogなどの関数を用いる場所でライブラリ関数の代わりにチャート法を用い,精度が高く記憶空間が限られている場合にチャート+補間方式を用いることを考えた.
次にatanの計算方法を改良し、
/* table of determine ATAN(x) */
const float atan_tb[] = {  //   (0.020)
0.00, 1.15, 2.29, 3.43, 4.57, 5.71 , 6.84, 7.97, 9.09, 10.20,
11.31, 12.41, 13.50, 14.57, 15.64, 16.70 , 17.74, 18.78, 19.80, 20.81,
21.80, 22.78, 23.75, 24.70, 25.64, 26.57 , 27.47, 28.37, 29.25, 30.11,
30.96, 31.80, 32.62, 33.42, 34.22, 34.99 , 35.75, 36.50, 37.23, 37.95,
38.66, 39.35, 40.03, 40.70, 41.35, 41.99 , 42.61, 43.23, 43.83, 44.42,
45.00, 45.57, 46.12, 46.67, 47.20, 47.73 , 48.24, 48.74, 49.24, 49.72,
50.19, 50.66, 51.12, 51.56, 52.00, 52.43 , 52.85, 53.27, 53.67, 54.07,
54.46, 54.85, 55.22, 55.59, 55.95, 56.31 , 56.66, 57.00, 57.34, 57.67,
57.99, 58.31, 58.63, 58.93, 59.24, 59.53 , 59.83 
};

y = atan_tb[((uint16_t)(x*100)) >> 1];

atanのテーブルを作成するにはMatlabを使用します.補間が必要な場合、例えばatan_tbの精度は0.02であるが,少数の場合ではatanを0.01の精度にすることを望んでおり,0.01でテーブルを構築するとテーブルのデータ記憶量を1倍に拡大し,0.02の精度テーブルに基づいて補間を再利用できる方式である.
たとえば、atan(0.03)を計算するには、表からatan(0.02)とatan(0.04)を調べることができます.線形補間のみを使用すると、
atan(0.03) = (atan(0.02) + atan(0.04)) / 2

プログラムのロジックをチェックしてください
バカに次のようなプログラムを書いたことがあります
uint8_t dir;  //  3      ,   switch    

int dist_switch(int a, int b, int c)
{
    int max_dist;
    int min_dist;
    int result = 0;

    switch (dir) {
    case 0x00: break;
    case 0x01: max=a;min=b;break;
    case 0x02: max=a;min=c;break;
    case 0x03: max=b;min=a;break;
    case 0x04: max=b;min=c;break;
    case 0x05: max=c;min=a;break;
    case 0x06: max=c;min=b;break;
    case 0x07: break;
    default: break;
    }

    result = max * 100 / (min + max);

    return result;
}

どう見ても文法の問題はなく、switchのbreak文も加わっています.
問題は、dirの低い3ビットが符号化されており、最大符号化個数は8であるべきである.実際に6種類しか使われていないため、switchでは他の2種類の符号化にbreakを使用しているので、問題が出てきました.もし私のdir=0 x 00だったらどうなりますか.switch文はもちろん問題ありません.問題は次の文です.
result = max * 100 / (min + max);

dir=0 x 00はmaxとminに対していかなる付与も行わず、他の場所にも与えられなかった.したがって、maxおよびminは、RAMで実行可能なローカル変数としてランダムな値になりますが、Flashに書き込むと、このローカル変数の不確実性が直接戻ってFlashダウンタイムになります.
したがって、switchおよびifについては...else...の論理的な問題は、範囲だけに注目することはできません.コンテキストをよくチェックしてください.
プログラム中の除算演算については特にご配慮ください
x=a/bでbが0の場合、このようなプログラムがFlashに書き込まれるとDSPがフリーズすることになります.できれば除算演算をシフト演算にできるだけ変換します.
たとえば、y=x/0.02を計算するには、1つの番号の変換方法は次のとおりです.
y=(uint32_t)(x*100)/2=((uint32_t)(x*100) >> 1);

さらに、*100をシフトの代わりに使用することもできます.
uint32_t tmp_x = (uint32_t)x;
y = ((tmp_x<<6) + (tmp_x<<5) + (tmp_x<<2)) >> 1;

これで除算演算は二度と見えなくなります.