4

ARM7TDMI プロセッサを使用して組み込みシステムに取り組んでいます。

タイム クリティカルな ISR では、ハードウェア レジスタから SRAM に 24 個の 16 ビット値のスナップショット (コピー) を取得する必要があります。値は連続しており、配列として扱うことができます。

データ バス (SRAM およびハードウェア レジスタへの) は 16 ビットで、ARM モード (8/32) で実行しています。

ショップでは、データをコピーするための最適な方法について話し合っています: 16 ビット量として、または 32 ビット量として。

私の主張は、ARM は 32 ビット モードであるため、2 つの 16 ビット命令でそれぞれ 1 つのフェッチを行うよりも、1 つの命令で 2 つの 16 ビット フェッチを高速に行うというものです。
また、フェッチする命令の数が半分になるため、時間が 1/2 短縮されます。

いずれかの方法をサポートするデータはありますか? (私の O'scopes はすべて割り当てられているため、組み込みシステムで測定を行うことはできません。また、ISR がミリ秒ごとに中断するため、膨大な時間を実行することもできません。) *(当社の JTAG Jet プローブは正確なプロファイリングの手段を提供しません)。

サンプルコード - 16 コピー:

#define MAX_16_BIT_VALUES 24U
uint16_t volatile * p_hardware;
uint16_t data_from_hardware[MAX_16_BIT_VALUES];
data_from_hardware[0] = p_hardware[0];
data_from_hardware[1] = p_hardware[1];
data_from_hardware[2] = p_hardware[2];
data_from_hardware[3] = p_hardware[3];
//...
data_from_hardware[20] = p_hardware[20];
data_from_hardware[21] = p_hardware[21];
data_from_hardware[22] = p_hardware[22];
data_from_hardware[23] = p_hardware[23];

サンプル コード、32 ビット コピー:

uint32_t * p_data_from_hardware = (uint32_t *)&data_from_hardware[0];
uint32_t volatile * p_hardware_32_ptr = (uint32_t volatile *) p_hardware;
p_data_from_hardware[0] = p_hardware_32_ptr[0];
p_data_from_hardware[1] = p_hardware_32_ptr[1];
p_data_from_hardware[2] = p_hardware_32_ptr[2];
p_data_from_hardware[3] = p_hardware_32_ptr[3];
//...
p_data_from_hardware[ 8] = p_hardware_32_ptr[ 8];
p_data_from_hardware[ 9] = p_hardware_32_ptr[ 9];
p_data_from_hardware[10] = p_hardware_32_ptr[10];
p_data_from_hardware[11] = p_hardware_32_ptr[11];

詳細: 8/32 ビット モードで動作する ARM7TDMI プロセッサ、IAR EW コンパイラ。

注: コードは、命令キャッシュのリロードを防ぐために展開されます。
注: アセンブリ言語のリストは、定数インデックスを使用してメモリにアクセスする方が、インクリメント ポインターを使用するよりも効率的であることを示しています。

編集 1: テスト

Chris Stratton のコメントによると、16 ビット FPGA レジスタで 32 ビット フェッチを行うときに問題が発生しているため、32 ビット最適化はできません。

そうは言っても、DMA を使用してプロファイリングしました。DMA コントローラーを使用することによるパフォーマンスの向上は、30 us (マイクロ秒) でした。私たちのプロジェクトでは、時間を大幅に節約したいと考えているため、この最適化は意味がありません。この実験は、転送するデータが多い場合、または転送が並列である場合、DMA が非常に役立つことを示しました。

興味深いことに、DMA のセットアップには 17 命令が必要でした。

4

1 に答える 1

1

速度が最も重要である場合、ハードウェアがそれをサポートできる場合の最善の策は、次のようなアセンブリ言語ルーチンになります。

; Assume R0 holds source base and R1 holds destination base
PUSH   {R4-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
POP    {R4-R7}

ARM7TDMI では、32 ビット バスを使用する場合、LDR に 3 サイクル、STR に 2 サイクルかかると思います。LDRMIA/STRMIA で n ワードをロードまたはストアするには、3+n サイクルが必要です。したがって、12 個の LDR と 12 個の STR には 60 サイクルが必要ですが、上記のシーケンスには 50 サイクルが必要です (レジスタの保存/復元を含む)。16 ビット バスを使用すると、すべての 32 ビット ロードまたはストアに余分なサイクル ペナルティが追加されると予想されますが、LDM* および STM* 命令が各 32 ビット操作を 2 つの 16 ビット操作に分割する場合でも、特にコードを 16 ビット メモリからフェッチする必要がある場合は、個別のロードとストアよりもはるかに高速になります。

于 2013-09-17T20:12:00.453 に答える