最初に、私が取り組んでいるマシンについて少し説明します (これは、FPGA と 2 つの CPU を含む SoC を備えた SOM であり、そのうちの 1 つで Linux OS が実行されています)。
特徴:
- ボード : Microzed
- SoC: Zynq 7020
- OS : ペタリナックス 2019.2
- カーネル バージョン: 4.19.0-xilinx-v2019.2
- プロセッサの種類: ARMv7 プロセッサ rev 0 v7l (armv7l)
BRAM メモリへの標準 AXI4 インターフェイスを提供する FPGA に実装されたカスタム ペリフェラルがあります (このコンポーネントのおかげです)。この周辺機器は私のデバイス ツリーに登録されており、カーネルの汎用 uio ドライバーを介してアクセスできます (これに関する詳細なドキュメント)。
BRAM メモリのサイズは 32kB です。に表示されるマッピング特性は次の/sys/class/uio/uioX/maps/map0/
とおりです。
- アドレス = 0x40000000
- オフセット = 0x0
- サイズ = 0x00008000
この BRAM メモリを読み取り、内部の内容をテキスト ファイルに記録するだけの C コードを作成しています。そうするために、mmap
(ここにそのマニュアルページ/dev/uioX
があります)を使用して、 (私のデバイスに対応する)にあるファイルのいくつかのメモリプロジェクションを作成します。
必要なファイル ページのみを使用し、ページごとにファイル ページをより正確にマッピングしたい。1 つのページのマッピングを作成するために使用する関数を次に示します。
/**
* @brief Get a pointer to the corresponding file page
*
* @param filePage file page number
* @param fd pointer where the file descriptor will be stored
* @return int*
*/
int *getFilePagePointer(int *fd, unsigned int filePage)
{
// open driver file
*fd = open("/dev/uio1", O_RDWR);
if (*fd == -1)
{
int errsv = errno;
fprintf(stderr, "Error while opening /dev/uio1 : errno %d (%s).\n", errsv, strerror(errsv));
exit(EXIT_FAILURE);
}
// choose projection parameters
int length = sysconf(_SC_PAGE_SIZE);
int offset = filePage * sysconf(_SC_PAGE_SIZE);
// create mapping
void *filePagePointer = mmap((void *)NULL, (size_t)length, PROT_READ, MAP_PRIVATE, *fd, (off_t)offset);
if (filePagePointer == MAP_FAILED)
{
int errsv = errno;
fprintf(stderr, "Error while mapping file page : errno %d (%s).\n", errsv, strerror(errsv));
exit(EXIT_FAILURE);
}
return (int *)filePagePointer;
}
そして問題: filePage
(オフセット)0
が の場合は完全に機能しますが、厳密に正の場合は で失敗しerrno = 22
ます。
マニュアルページで何かを見逃していない限り、すべてのパラメーターは有効です (offset
は の倍数でありsysconf(_SC_PAGE_SIZE)
、addr
isは厳密に正でありNULL
、length
大きすぎず、フラグは正しいです)。では、なぜ EINVAL なのか?...