Utrzymuję kod obszaru użytkownika, który komunikuje się z FPGA przez SPI. W tej chwili jest sondowanie, aby sprawdzić, czy istnieją dane, na które należy zareagować, a których nie jestem zachwycony. The (mocno uproszczony) struktura nici łączności wygląda następująco:Czy mogę wybrać() na deskryptorze pliku/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
}
}
}
ja bym naprawdę preferują rozwiązania opartego na zdarzeniu nad poll-and-sen. Pierwszą rzeczą, która przyszła mi do głowy robi select() na deskryptor pliku spidev zamiast sprawdzania jakiś rejestr co X sekund, coś
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);
}
rzeczą jest nie mogę znaleźć żadnych przykładów osób obsługujących jak SPI to i zastanawiam się, czy może istnieje ku temu dobry powód. Czy Can/dev/spidev może być używany w ten sposób? Czy zrobi to coś głupiego jak zawsze/nigdy nie będąc "gotowymi do czytania"? Czy może być wykonane, aby zachowywać się tak, jak chcę? Czy jest zależny od sprzętu? Nie mam nic przeciwko małym hakerom, jeśli jest to konieczne, ale nie jestem pewien, czy/gdzie powinienem szukać.
'select()' powinno działać. Dane są gotowe do czytania, gdy tylko gotowy jest jeden bajt w buforze jądra. Nie mogę jednak zagwarantować, że autor sterownika urządzenia nie ciął żadnych narożników. – fuz
Jeśli sterownik jest dźwiękowy, powinno działać 'select()'. Pamiętaj o tych kwestiach, ale dobrze jest napisać odpowiedni test - nawet jeśli wszystko działa na urządzeniu, na które teraz celujesz, będziesz wdzięczny za test, jeśli później spróbujesz zbudować urządzenie lub sterownik na którym zawodzi. –
* "Naprawdę wolałbym rozwiązanie oparte na zdarzeniach" * - Jeśli sterownik SPI zmusza do odpytywania, ponieważ nie używa przerwania, to nie ma magicznej procedury, która zmieni sytuację.Używanie ** select() ** (które może nie działać z *** *** przestrzenią użytkownika *** SPI) spowoduje jedynie przesunięcie odpytywania kodu i ukryje się za wywołaniem libc. Jeśli chcesz sterować zdarzeniami we/wy, musisz użyć/napisać sterownik, który generuje przerwań i usług. – sawdust