私はTerasic-SoCKIT(fpgaとarm cortex a9)を持っており、HPSでLinuxを実行しています。 「request_mem_region」および「ioremap」関数を使用して単純な文字ドライバを作成しながら、メモリマップされたI / Oにアクセスしようとしています。
メモリマッピングIOは、データをFPGAに転送するために使用できるAXIバスです。各書き込みには約6usかかり、私のアプリケーションでは1us未満でなければなりません。また、ドライバは数回の書き込み後にマッピングされたIOへの書き込みを停止します(FPGAのデータが変更されているのを見ることはできません。ドライバのバッファがいっぱいですか?)。
問題は、私が何かを見逃しているのでしょうか、それとも書き込みが仮想アドレスから実際のアドレスになるため、より高速ではないということです。仮想アドレスで書き込む速度が遅い場合に速度を上げる方法はありますか? ARMにDMACがあることを知っていますが、まだ見ていません。
ありがとう、カルティック
申し訳ありません。ユーザー空間コードで時間を測定しているという事実を誰にも知らせることができませんでした。後でドライバに書き込むのに要した時間をナノ秒単位で確認しました。だから、ほとんどの場合、ユーザー空間でカーネルに書き込まれるようです。
だから私はもっと読み、ioremap()が物理アドレスをカーネル仮想アドレスにマップし、remap_pfn_range()が物理アドレス/ IOメモリをユーザーの仮想空間にマップすることを知りました(これは私が必要なことです)。書き込み)。私は単純なmmapの例を使用しました -http://web.cecs.pdx.edu/~jrb/ui/linux/examples.dir/simple/simple.cカーネルドライバーで。次のコードは私のユーザースペースコードです。
using namespace std;
#include <iostream>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <ctime>
#define PAGE_SIZE 4096
#define HPS2FPGA_BRIDGE_BASE 0xc0000000
#define BLINK_OFFSET 0x0
volatile unsigned char *blink_mem;
void *bridge_map;
int main()
{
int fd, ret = EXIT_FAILURE;
unsigned int i;
unsigned char value;
int dummy;
off_t blink_base = HPS2FPGA_BRIDGE_BASE;
clock_t start, stop;
double duration;
/* open the memory device file */
fd = open("/dev/HPS2FPGA", O_RDWR|O_SYNC);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
/* map the LWHPS2FPGA bridge into process memory */
bridge_map = mmap(NULL, PAGE_SIZE, PROT_WRITE|PROT_READ|PROT_EXEC, MAP_SHARED,
fd, blink_base);
if (bridge_map == MAP_FAILED) {
perror("mmap");
goto cleanup;
}
/* get the delay_ctrl peripheral's base address */
blink_mem = (unsigned char *) (bridge_map + BLINK_OFFSET);
start = clock();
/* write the value */
for(i = 0; i < 1000000; i++)
{
*blink_mem = i;
dummy = *blink_mem;
}
stop = clock();
duration = ( stop - start ) / (double) CLOCKS_PER_SEC;
printf("%f", duration);
if (munmap(bridge_map, PAGE_SIZE) < 0) {
perror("munmap");
goto cleanup;
}
ret = 0;
cleanup:
close(fd);
return ret;
}
mmapから返された仮想アドレス空間に書き込んでいますが、そのアドレスの値を読み書きすることはできますが、FPGAの値が更新されていることはわかりません。
ユーザーの仮想空間に書き込むときに物理アドレスはどのように使用されますか?実際のアドレス空間が実際に記録されているかどうかをデバッグして確認する方法はありますか?
答え1
さて、この質問の主題は次のとおりです。毛...メモリマップされたI / O(正しく実行されます)は、アクセスされるハードウェアに対してプロセッサが実行するのと同じくらい高速です。 )カーネルに書き込まれます」)。
ただし、アドレスを読み書きするときに何が起こるのかを考慮する必要があります。ここに問題があります。ほとんどのアーキテクチャには、仮想から物理へ、物理からデバイスへの2つのマッピングがあります。 1つ目は仮想メモリハードウェアに設定され、2つ目はメモリコントローラに設定されます。
マッピングを除くすべてのアクセスは通常、次のように行われます。隠れ家ハードウェアなので、アクセスをキャッシュするかどうかを決定する必要があります。アクセスされる基本デバイスが一種のRAMである場合は、通常アクセスをキャッシュしようとします。他のタイプのデバイスでは通常必要ありません。
考慮すべきその他の点(VMマッピングがVMハードウェアにあるかどうか、アクセス幅と期間、優先順位、権限など)があるかもしれませんが、キャッシュが最初です。
@Karthikの場合はそうではなかったのでオフキャッシュのタイプに応じてマップにキャッシュされるか、キャッシュ全体にキャッシュされます。ワイヤーアドレスに書き込むときに書き込み中(write-through)または書き込みが遅れる(write-back)(キャッシュの詳細を知りたい場合は、次のことを試してください)。これ)。
特定の(後続の)質問に答えるために、仮想アドレスマッピングが完了し、キャッシュが操作を完了すると、アクセスはメモリコントローラに移動します。ハードウェアはアクセスするバスおよび/またはデバイスを決定し、「正しい動作」。一般に、アサーションに関連するハードウェア「モノ」チップ選択および/または書き込み可能信号、一部または全部をコピーできます物理住所住所行、たぶん一部タイミング設定、等。
...この問題をデバッグする最良の方法はアナライザどのようなデバイスやバスが接続されているか、難しすぎる、または高価な場合は、メモリコントローラでデバッグをサポートすることもできます。
blink_mem
もう一つのマイナーだが重要な点は、上記のコードの説明を参照してください。揮発性物質型修飾子は非常に重要です。アドレスへのアクセスを破壊しないようにコンパイラに指示します。これに加えて、メモリアクセスに関連する特別なパイプコマンドも知っておく必要があります(参照:アイオpowerpc教育 - ユーモアのセンスのある人 :-)
最後に、コメントで話した内容をもう一度申し上げると、電話をかけるときにこれが質問に対する実際の答えであることがわかりました。remap_pfn_range()あなた閉じる最後のパラメータで指定されたページ保護を変更してキャッシュします(タンパク質) 使用pgprot_noncached()マクロ。また読んでくださいこれそしてこれ特にこれ。乾杯!