2013-04-09 25 views
6

Tôi hy vọng sẽ tìm thấy một số trợ giúp ngay cả khi vấn đề này có thể là phần cứng nhiều hơn phần mềm liên quan (chúng ta sẽ thấy). Tôi đang làm việc trên một bảng tùy chỉnh dựa trên bộ vi xử lý Freescales P1021 (ppc, e500v2 lõi). Một PCB bên ngoài sẽ được kết nối và có thể được cấu hình bởi SPI. Các thông số kỹ thuật của PCB bên ngoài này đọc vì nó mong đợi một lệnh 2 byte ở chế độ song công hoàn chỉnh và chỉ byte cuối được sử dụng để truyền dữ liệu trở lại trên MISO.Spidev không viết/đọc đồng thời bằng ioctl

Biết điều này tôi hiện đang làm việc để chuẩn bị một số phần mềm để kiểm tra thiết bị này. Vì vậy, tôi bắt đầu với chương trình spi_test nổi tiếng.

[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

Các tín hiệu cho thấy 608 đồng hồ và có vẻ như chỉ có dữ liệu trong nửa đầu. Tôi quyết định điều tra và kiểm tra nó với loopback - shorcutting MOSI-MISO lặp lại dữ liệu vào bộ đệm rx. Kết quả:

[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

tín hiệu này cho thấy, rằng toàn bộ bức điện được lặp lại cho bất cứ lý do (Tôi không biết tại sao). Tuy nhiên, chương trình hiển thị dữ liệu đã nhận trong bảng điều khiển chính xác, vì vậy nó có thể giống như spi_test mong đợi nó.

Hơn nữa tôi thao tác các mẫu mà sẽ được gửi trong chương trình này xuống đến 2 byte (để mô phỏng các định dạng lệnh yêu cầu tôi nhằm mục đích cho) như thế này:

#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 

Nhưng khi tôi không mong đợi 32bits được chuyển ra đến xe buýt SPI - thay vì 16. Trong hai byte đầu tiên MOSI cung cấp cả hai byte từ tx [] và cho 2 byte khác nó là thấp/0. Dưới đây là kết quả của giao diện điều khiển đầu ra và tín hiệu:

[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

Và thậm chí nếu tôi loopback MOSI để miso không nhận được dữ liệu (giao diện điều khiển đầu ra vẫn là tiếp nhận cùng "00 00"):

(chỉ truyền)

Pic4

tôi chơi xung quanh một chút với tất cả các thông số và quyết định thay đổi chương trình thử nghiệm sử dụng half duplex mode:

#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 

Vì đây là công cụ được biên dịch và thực hiện giống như mong đợi. SPI_CLK chu kỳ 16 lần cho 16 bit và MOSI cung cấp dữ liệu như mong đợi. sản lượng Cosole cho thấy không nhận được dữ liệu và tín hiệu cũng giống như mong đợi:

[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

Trên thực tế có vẻ như với tôi rằng thay vì làm 2 byte đầy đủ chuyển duplex tôi làm một truyền N byte tiếp bằng một byte N nhận được.

Trên thực tế có hai câu hỏi:

  1. Tại sao 0xAA, 0x81 và 0x00, 0x00 được truyền?
  2. Tại sao (sử dụng loopback) mã gốc có thể lấy lại dữ liệu trong bộ đệm rx nhưng nếu giảm xuống 2 byte thì không nhận được dữ liệu?
+0

Post hình ảnh ở nơi khác và thêm các liên kết với họ trong câu trả lời - một người dùng đại diện cao hơn sau đó có thể chỉnh sửa câu trả lời của bạn để bao gồm họ –

+0

tôi sẽ kiểm tra ngày hôm nay nếu spidev đã được biên soạn với SPI_MASTER_HALF_DUPLEX cờ được kích hoạt để buộc thiết bị spi song công một nửa. – stede

+0

SPI_MASTER_HALF_DUPLEX chưa được đặt. – stede

Trả lời

1

Vâng, bài đăng là yên tĩnh áp đảo. Tôi chỉ đọc một vài phần và gần đây đã liên lạc với SPI trên Linux. Tuy nhiên, như đã đề cập trong https://www.kernel.org/doc/Documentation/spi/spidev không đọc/ghi không đồng bộ trong không gian người dùng. Đọc/ghi AFAIK chỉ là một trình bao bọc xung quanh fcntl. Vì vậy, bạn sẽ cần phải viết mô-đun hạt nhân của riêng bạn để đạt được I/O không đồng bộ.

+0

Câu trả lời này có vẻ sai. Bài viết https://www.kernel.org/doc/Documentation/spi/spidev nói cụ thể là "Sử dụng các yêu cầu ioctl(), chuyển giao song công ... đều có sẵn". Và kiểm tra spi (ví dụ: https://github.com/KnCMiner/spi-test/blob/master/spi-test.c#L97) sử dụng ioctl() đó. –

0

Tôi biết đây là một chủ đề rất cũ nhưng tôi đã sử dụng spidev trên RT5350 chạy OpenWRT. Tôi nhận được kết quả tương tự như bạn; Tôi chỉ không thể nhận được một chuyển giao song công đầy đủ xảy ra. Đọc datasheet RT5350 nó xuất hiện rằng phần cứng chỉ có thể làm một nửa chuyển SPI hai chiều. Mỗi lần chuyển là viết (byte đầu ra trên MOSI, không đọc bất cứ điều gì), hoặc đọc (số không đầu ra trên MOSI, đọc MISO).

Tôi không thể lấy biểu dữ liệu cho chip P1021 của bạn, nhưng xem xét sự giống nhau về kết quả của chúng tôi, tôi muốn nói rằng phần cứng SPI của nó được triển khai theo cách tương tự.

Điều này có nghĩa là mô-đun hạt nhân không phải là câu trả lời (ioctl SPI_IOC_MESSAGE cuối cùng cũng gọi spi_async()). Cách duy nhất để làm SPI full duplex là sử dụng GPIO trong phần mềm.

RT5350 tham khảo: http://forum.vocore.io/viewtopic.php?f=3&t=72#p233