私は、SPIを介してFPGAと会話するユーザー空間コードをいくつか維持しています。今すぐ、私が感心していないデータがあるかどうかを調べるためにポーリングしています。 COMMスレッドの(重く-簡体字)の構造は次のようになります。/dev/spidevファイル記述子で()を選択できますか?
int spi_fd;
void do_transfer(char *buf, int len)
{
struct spi_ioc_transfer xfer;
memset(xfer, 0, sizeof(xfer));
ioctl_tell_some_fpga_register_heads_up();
xfer[0].len = len;
xfer[0].tx_buf = NULL;
xfer[0].rx_buf = buf;
ioctl(spi_fd, SPI_IOC_MESSAGE(1), xfer);
ioctl_tell_some_fpga_register_were_done();
}
void *comm_thread(void arg)
{
uint8_t config = SPI_MODE_3;
__u32 speed = 4000000;
char buffer[5120];
spi_fd = open("/dev/spidev1.0", O_RDWR);
ioctl(spi_fd, SPI_IOC_WR_MODE, &config);
ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
while(1) {
sleep(2); //ugh
if(ioctl_read_some_fpga_register_that_says_if_theres_data())
{
do_transfer(buffer, some_small_number_of_bytes());
do_stuff(buffer); //you get the picture
}
}
}
私は本当にをいただきたいポーリングおよびスリープオーバーイベントベースのソリューションを好みます。心に来た最初の事は、私は次のようにSPIを扱う人々のいずれかの例を見つけることができませんされて
fd_set myset;
while(1) {
FD_ZERO(&myset);
FD_SET(spi_fd, &myset);
select(spi_fd + 1, &myset, NULL, NULL, NULL);
do_transfer(buffer, some_small_number_of_bytes());
do_stuff(buffer);
}
シングのようないくつかのレジスタX秒ごとに、何かをチェックするのではなく、spidevファイルディスクリプタ上)(選択をしていましたそれに、それに正当な理由があるのだろうかと思っています。/dev/spidevをこの方法で使用できますか? いつものようにうまくやっている/決して読むことができないだろう? にすることができますか?私が望むように動作する?ハードウェアに依存していますか?私は、必要ならカーネルドライバのハッキングを嫌うわけではありませんが、探している必要があるかどうかはわかりません。
'select()'が動作するはずです。カーネルのバッファに1バイトの準備が整うとすぐに、データを読み込む準備が整います。しかし、私は、デバイスドライバの作者がコーナーを削っていないことを保証することはできません。 – fuz
ドライバが健全な場合、 'select()'が動作するはずです。あなたがこれらの問題に気をつけている間は、適切なテストを書くのが楽しいでしょう - あなたが今ターゲットにしているデバイスですべてが機能しても、後でデバイスやドライバをビルドしようとすると、テストに感謝しますそれは失敗する。 –
* "私は実際にはイベントベースのソリューションを望んでいます" * - SPIドライバが割り込みを使用しないためにポーリングを強制する場合、状況を変える魔法のルーチンはありません。** select()**(これは***のユーザースペース***のSPIドライバでは動作しません)を使うと、あなたのコードからポーリングだけを移動し、libc呼び出しの背後に隠れます。イベントドリブンのI/Oが必要な場合は、&サービス割り込みを生成するドライバを使用/書き込みする必要があります。 – sawdust