2016-04-14 17 views
6

私は、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をこの方法で使用できますか? いつものようにうまくやっている/決して読むことができないだろうにすることができますか?私が望むように動作する?ハードウェアに依存していますか?私は、必要ならカーネルドライバのハッキングを嫌うわけではありませんが、探している必要があるかどうかはわかりません。

+1

'select()'が動作するはずです。カーネルのバッファに1バイトの準備が整うとすぐに、データを読み込む準備が整います。しかし、私は、デバイスドライバの作者がコーナーを削っていないことを保証することはできません。 – fuz

+0

ドライバが健全な場合、 'select()'が動作するはずです。あなたがこれらの問題に気をつけている間は、適切なテストを書くのが楽しいでしょう - あなたが今ターゲットにしているデバイスですべてが機能しても、後でデバイスやドライバをビルドしようとすると、テストに感謝しますそれは失敗する。 –

+1

* "私は実際にはイベントベースのソリューションを望んでいます" * - SPIドライバが割り込みを使用しないためにポーリングを強制する場合、状況を変える魔法のルーチンはありません。** select()**(これは***のユーザースペース***のSPIドライバでは動作しません)を使うと、あなたのコードからポーリングだけを移動し、libc呼び出しの背後に隠れます。イベントドリブンのI/Oが必要な場合は、&サービス割り込みを生成するドライバを使用/書き込みする必要があります。 – sawdust

答えて

2

私は/ dev/spidevファイル記述子で()を選択できますか?


spidev documentation状態が

At this time there is no async I/O support; everything is purely synchronous. 

さらに重要なspidev driverは、ポーリングファイル操作をサポートしていません。 select() syscallは、デバイスドライバがポーリングをサポートする必要があります。

670 static const struct file_operations spidev_fops = { 
671   .owner =  THIS_MODULE, 
672   /* REVISIT switch to aio primitives, so that userspace 
673   * gets more complete API coverage. It'll simplify things 
674   * too, except for the locking. 
675   */ 
676   .write =  spidev_write, 
677   .read =   spidev_read, 
678   .unlocked_ioctl = spidev_ioctl, 
679   .compat_ioctl = spidev_compat_ioctl, 
680   .open =   spidev_open, 
681   .release =  spidev_release, 
682   .llseek =  no_llseek, 
683 }; 
+1

非同期I/Oサポートも、デバイスがデータを提供する準備ができるまでブロックする方法もない場合、それはかなり悲しいことです。 :( –

+0

@DavidSchwartz - spidevドライバは、プロダクション品質のドライバを意図したものではなく、SPIドライバモデルのプロトコルドライバの迅速な開発とテストを可能にするユーザスペースのクルーギーです。典型的には、GPIO割り込みなどのHWクロックがあります。 – sawdust

1

これはLinux SPIドライバの質問になる前に、ステータス情報をFPGAから取得する方法を調べる必要があります。

FPGAが割り込みまたは注意ラインを駆動するようなことをしない限り、SPIマスタ(おそらくCPUに接続されている)はFPGAをポーリングするためにSPI動作を行う必要があります。そのため、定期的にポーリングを行うカーネルスペースにコードがないか、またはそれまでは、ユーザースペースが有意義にselect()するためにドライバ内で利用可能な情報はありません。

注意:FPGAからプロセッサへの注意信号が戻ってきたら(他のものがそれを共有しているかどうかによって、MISOを逸脱しているように単純にすることができます)、おそらくそれを割り込みとして監視できますカーネルのSPIドライバで、またはselect()を実行できるユーザ空間割り込みインタフェースを別途使用することによって実行できます。

もしそうでなければ、SPIを介して状態のポーリングをカスタムカーネルドライバに移動することと、ユーザー空間に残すこととのトレードオフを評価する必要があります。

関連する問題