2013-04-09 11 views
6

Mam nadzieję, że znajdę pomoc, nawet jeśli ten problem może być więcej sprzętu niż oprogramowania (zobaczymy). Pracuję na niestandardowej płycie opartej na procesorze Freescales P1021 (ppc, rdzeń e500v2). Zewnętrzna płytka PCB zostanie podłączona i może być skonfigurowana przez SPI. Specyfikacje tej zewnętrznej płytki drukowanej są odczytywane w oczekiwaniu na 2-bajtowe polecenie w trybie pełnego dupleksu i że tylko ostatni bajt jest używany do przesyłania danych z powrotem do MISO.Spidev nie pisze/czyta jednocześnie, używając ioctl

Wiedząc, że obecnie pracuję nad przygotowaniem niektórych programów do przetestowania tego urządzenia. Zacząłem więc od znanego programu spi_test.

[email protected]:~# ./spi_test -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 
[email protected]:~# 

Pic1

Sygnał pokazuje 608 zegary i wydaje się, że są tylko dane w pierwszej połowie. Decyduję się zbadać i przetestować go z pętlą zwrotną - shorcutting MOSI-MISO zapętla dane do bufora rx. Wyniki:

[email protected]:~# ./spi_test -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

FF FF FF FF FF FF 
40 00 00 00 00 95 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
DE AD BE EF BA AD 
F0 0D 
[email protected]:~# 

Pic2

Te sygnały ujawnia, że ​​cała telegram jest powtarzany z jakiegokolwiek powodu (nie wiem dlaczego). Jednak program poprawnie pokazuje odebrane dane w konsoli, więc może być tak, jak spi_test tego oczekiwał.

Dalsze manipulować wzór, który zostanie wysłany w tym programie w dół do 2 bajtów (do symulacji żądany format polecenia Dążę do) tak:

#ifdef ORIG 
    uint8_t tx[] = { 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
     0xF0, 0x0D, 
    }; 
#else 
    uint8_t tx[] = { 
     0xAA, 0x81, 
    }; 
#endif 

Ale nie spodziewałem się 32-bitowego są przesunięte do magistrali SPI - zamiast 16. Podczas pierwszych dwóch bajtów MOSI dostarcza oba bajty z tx [], a dla pozostałych 2 bajtów jest niski/0. Oto wyniki wyjścia konsoli i sygnały:

[email protected]:~# ./spi_test_2bytes -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 
[email protected]:~# 

Pic3

i odbierana nawet gdybym LOOPBACK MOSI do miso żadnych danych (wyjście konsola jest wciąż ten sam odbierający „00 00”):

tryb

Pic4

Gram się trochę ze wszystkimi parametrami i podjąć decyzję o zmianie programu testowego użyć pół dupleksu (transmitować tylko):

#ifdef ORIG 
    uint8_t tx[] = { 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
     0xF0, 0x0D, 
    }; 
#else 
    uint8_t tx[] = { 
     0xAA, 0x81, 
    }; 
#endif 
    uint8_t rx[ARRAY_SIZE(tx)] = {0, }; 
    struct spi_ioc_transfer tr = { 
     .tx_buf = (unsigned long)tx, 
#ifdef ORIG  
     .rx_buf = (unsigned long)rx, 
#else 
     .rx_buf = 0, 
#endif 

Ponieważ jest to skompilowane i wykonane, rzeczy są jak oczekiwano. SPI_CLK wykonuje 16 cykli dla 16 bitów, a MOSI dostarcza danych zgodnie z oczekiwaniami. Wyjście Cosole nie wykazuje otrzymane dane i sygnały są jak oczekiwano:

[email protected]:~# ./spi_test_2bytes -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 
[email protected]:~# 

Pic5

Pic6

Właściwie wydaje mi się, że zamiast robić 2 bajty pełne przeniesienie dupleksu robię nadawczo N bajtowy przez N-bajtowy odbiór.

Właściwie istnieją dwa pytania:

  1. Dlaczego 0xAA, 0x81 i 0x00, 0x00 jest transmitowane?
  2. Dlaczego (używając sprzężenia zwrotnego) oryginalny kod jest w stanie odzyskać dane w buforze rx, ale jeśli zostanie zredukowany do 2 bajtów, żadne dane nie zostaną odebrane?
+0

opublikować zdjęcia gdzie indziej i dodać linki do nich w odpowiedzi - użytkownik wyższe rep można następnie edytować swoją odpowiedź na to im –

+0

będę sprawdzał dziś jeśli spidev został skompilowany z SPI_MASTER_HALF_DUPLEX flagą włączone, które zmusza urządzenie SPI do półdupleksu. – stede

+0

SPI_MASTER_HALF_DUPLEX nie został ustawiony. – stede

Odpowiedz

1

Cóż, poczta jest przytłaczająca. Po prostu przeczytałem kilka części i ostatnio nawiązałem kontakt z SPI na Linuksie. Jednak jak wspomniano w asynchroniczny odczyt/zapis nie jest dostępny w przestrzeni użytkownika. AFAIK read/write jest po prostu opakowaniem wokół fcntl. W związku z tym musisz napisać własny moduł jądra, aby uzyskać asynchroniczne operacje we/wy.

+0

Ta odpowiedź wydaje się błędna. Artykuł https://www.kernel.org/doc/Documentation/spi/spidev mówi dokładnie "Korzystanie z żądań ioctl(), transfery full duplex ... są ... dostępne.". I spi-test (np. Https://github.com/KnCMiner/spi-test/blob/master/spi-test.c#L97) używa tego ioctl(). –

0

Wiem, że to bardzo stary wątek, ale używam spidev na RT5350 z OpenWRT. Otrzymuję dokładnie takie same wyniki jak ty; Nie jestem w stanie uzyskać pełnego transferu dupleksowego. Odczytując arkusz danych RT5350 okazuje się, że sprzęt jest w stanie wykonać tylko półdupleksowe transfery SPI. Każdy transfer to albo zapis (bajty wyjściowe na MOSI, nic nie czytaj), albo odczyt (zera wyjściowe na MOSI, odczytaj MISO).

Nie mogę pobrać arkusza danych dla układu P1021, ale biorąc pod uwagę podobieństwo naszych wyników, powiedziałbym, że SPI sprzętu jest zaimplementowany w podobny sposób.

Oznacza to, że moduł jądra nie jest odpowiedzią (ioctl SPI_IOC_MESSAGE ostatecznie wywołuje spi_async()). Jedynym sposobem na uzyskanie pełnego dupleksu SPI jest używanie GPIO w oprogramowaniu.

odniesienia RT5350: http://forum.vocore.io/viewtopic.php?f=3&t=72#p233

Powiązane problemy