Raspberry Pi có thể tin cậy một chút khi đập một chuỗi 9600 baud và có mã ví dụ không?


29

Tôi tự hỏi làm thế nào khả thi khi sử dụng bitbanging để lái một chuỗi 9600 baud thông qua các chân GPIO trên Raspberry Pi.

Rõ ràng, Linux không phải là một nền tảng tốt cho bitbanging, vì có một số lượng lớn trình điều khiển và các ngắt khác có thể chặn CPU trong thời gian dài (1-10ms). Tuy nhiên, gần đây tình hình đã trở nên tốt hơn rất nhiều và một số chế độ tiền chế hiện được kích hoạt thường xuyên trong các hạt nhân. Tôi cũng nghi ngờ một hạt nhân được vá thời gian thực có thể dễ dàng được sử dụng trên Raspberry Pi, và phần cứng và trình điều khiển được kết nối có thể được chọn cẩn thận.

Tiêu chuẩn của tôi về độ tin cậy là nó phải ở trong dung sai nối tiếp 9600 baud bình thường trong hầu hết thời gian. Tôi hiện không chắc chắn có bao nhiêu lỗi có thể chấp nhận được trong thực tế, nhưng có sự truyền lại và xác nhận trong giao thức, vì vậy nó ít nhất là khoan dung.

Vì vậy, câu hỏi của tôi là:

  • Phần mềm userland có thể tin cậy tốc độ bit-bang 9600 baud không?
  • Điều này có cần một kernel vá thời gian thực?
  • Có bao nhiêu lỗi tôi nên nói chung?

Ngoài ra, có mã ví dụ nào thực hiện nối tiếp qua đập GPIO không? Tôi biết về Arduino SoftSerial, nhưng đó là về nó.

Chỉ trong trường hợp, để giới hạn câu hỏi: đây không phải là giao diện nối tiếp tiêu chuẩn và UART của Raspberry Pi đã được sử dụng cho một liên kết nối tiếp khác. Tôi không muốn câu trả lời đề xuất phần cứng bên ngoài (như Gertboard hoặc Arduino) cũng như câu trả lời phụ thuộc vào UART.


1
+1 Câu hỏi hay. Tôi cũng sẽ quan tâm đến câu trả lời cho điều này. Tuy nhiên, câu hỏi reliabilitycó thể phụ thuộc vào hành động và kỳ vọng.
Jivings

2
RS-232 cần điện áp âm, nhưng liên kết nối tiếp này không sử dụng điện áp RS-232. Tôi không biết nhưng tôi tin rằng RPi yêu cầu bộ chuyển đổi tiêu chuẩn từ TTL sang RS-232, chẳng hạn như MAX 232 hoặc bất kỳ lựa chọn nào trong số hàng tá lựa chọn. Tuy nhiên, để rõ ràng, điều này không liên quan đến câu hỏi của tôi, tôi chỉ muốn trả lời.
Khỏa thân

4
Có một UART thứ hai trên các chân GPIO 14 & 15. Mặc dù vậy, nó không đầy đủ tính năng như bản chính
John La Rooy


1
@Nakenible bạn có thể vui lòng chia sẻ công việc của bạn? Tôi có một vấn đề tương tự và muốn xem bạn đã thực hiện nối tiếp thứ hai qua spi như thế nào. cảm ơn MSP

Câu trả lời:


15

Cuối cùng tôi đã giải quyết điều này, nhưng theo một cách khá không chính thống. Tôi đã từ bỏ bit-banging vì quá không đáng tin cậy và cố gắng tìm các giải pháp khác cho phép tôi làm điều tương tự mà không cần thêm phần cứng. Tôi đã xem xét việc viết trình điều khiển hạt nhân, điều này sẽ kích hoạt ngắt trên GPIO và sau đó cấu hình lại mã pin thành SPI và sử dụng SPI để đọc toàn bộ byte dữ liệu - nhưng sau đó tôi đã hiểu rõ hơn.

Tôi sử dụng SPI để lấy mẫu các dòng ở tốc độ bx 20 lần. Tôi hoàn toàn bỏ qua các chân SCLK và SS, kết nối đường dây RX với đường MISO và TX với MOSI. Điều này mang lại cho tôi chế độ xem giống như dao động (1 bit) trong dòng RX và thấy rõ các bit được truyền trong dòng nối tiếp:

00 00 00 00 00 00 
00 00 00 00 01 FF 
FF FF FF FF 00 00 
01 FF FF FF FF FF 
FF FF E0 00 00 00 
00 00 07 FF FF FF 
FF FF 

Từ đó, việc mã hóa để tìm ra các vị trí chính xác để lấy mẫu các bit dữ liệu thực tế là một vấn đề đơn giản. Phía gửi cũng tầm thường không kém, tôi chỉ cần chuyển đổi từng byte thành một luồng bit dài với bit start và bit stop đi kèm.

Lý do điều này hoạt động tốt hơn so với đập bit là vì SPI có đồng hồ riêng không bị đóng băng với kernel và các dòng gửi và nhận SPI có FIFO 16 byte để chuyển cũng độc lập với đóng băng kernel. Đối với 9600 baud, tôi đang sử dụng đồng hồ SPI 250kHz và điều đó có nghĩa là tôi có thể ngủ thậm chí trong một phần nghìn giây giữa việc làm đầy và làm cạn kiệt các FIFO mà không có bất kỳ lỗi truyền nào. Tuy nhiên, để đảm bảo an toàn, tôi đang sử dụng 300 giấc ngủ. Tôi đã thử nghiệm ngắn gọn về việc tôi có thể đẩy mức này bao xa và ít nhất một đồng hồ SPI 2 MHz vẫn có thể sử dụng được để giải pháp này có tỷ lệ baud cao hơn.

Một phần xấu của giải pháp này là trình điều khiển SPI kernel không hỗ trợ truyền bit như vậy. Điều này có nghĩa là tôi không thể làm điều này bằng cách viết mô-đun hạt nhân của riêng mình bằng trình điều khiển SPI kernel và tôi cũng không thể làm điều đó bằng cách sử dụng /dev/sdidev0.0 từ vùng người dùng. Tuy nhiên, trên Raspberry Pi, SPI và các thiết bị ngoại vi khác có thể truy cập trực tiếp từ vùng người dùng bằng mmap (): n / dev / mem, bỏ qua toàn bộ điều khiển kernel. Tôi không hài lòng lắm với điều này, nhưng nó hoạt động hoàn hảo và nó mang lại lợi ích bổ sung rằng các lỗi phân đoạn trong vùng người dùng không thể làm hỏng kernel (trừ khi vô tình làm hỏng các thiết bị ngoại vi khác). Đối với việc sử dụng CPU, 300 giấc ngủ dường như cung cấp cho tôi khoảng 7% CPU sử dụng liên tục, nhưng mã của tôi rất không tối ưu. Tăng thời lượng ngủ rõ ràng làm giảm việc sử dụng CPU trực tiếp.

Chỉnh sửa: Quên đề cập đến, tôi đã sử dụng thư viện bcm2835 đẹp để kiểm soát SPI từ vùng người dùng, mở rộng nó khi cần thiết.

Vì vậy, để tóm tắt: Tôi có thể truyền và nhận một cách đáng tin cậy trên một liên kết nối tiếp 9600 baud hoàn toàn từ vùng người dùng bằng cách sử dụng trực tiếp chip SPI qua / dev / mem ở 250kHz trên Raspberry Pi.


@ Nakedible - Bạn có thể xây dựng một chút hoặc cung cấp các liên kết trên phần mmap (). Tôi đang làm việc trên cùng một điều.
Jay K

Bạn có đang sử dụng phần cứng SPI để thực hiện việc truyền tải không?
Cheetah

Vâng, truyền công việc là tốt.
Khỏa thân

3
Bạn có thể vui lòng cung cấp hướng dẫn từng bước về cách bạn có thể gửi và nhận mã và chia sẻ mọi gói đã sửa đổi nếu bạn sử dụng thứ gì đó mà bạn tự vá ... TIA!
valentt

10

Dường như ít nhất là không có các bản vá thời gian thực (CONFIG_PREEMPT_RT), Raspberry Pi không thể tin cậy bit-bang một chuỗi 9600 baud.

Tôi đã sử dụng một trình kiểm tra độ trễ đơn giản, cấu hình tất cả các thứ bên linux một cách tối ưu (calendar_fifo, ưu tiên 99, cpu_dma_latench 0us, mlockall). Tôi đã thử ngủ 100 100sec (khoảng 9600 baud) và kiểm tra độ trễ tràn ngập trên một hệ thống yên tĩnh trong 2 phút. Kết quả là:

Tối thiểu: 12 trận đấu Trung bình: 24 trận đấu Tối đa: 282 trận đấu

Đây dường như là kết quả chung. Tối đa khác nhau trong các phép đo chậm hơn giữa 100 Patricksec và 300 Patricksec. Tôi cũng đã kiểm tra phân phối và có vẻ như đại đa số nằm trong phạm vi 24 trận đấu. Chỉ có một số ít vượt quá 50 trận, nhưng hầu như luôn có một số. Đôi khi cũng có độ trễ lớn, chẳng hạn như 4000, nhưng những điều này không đủ phổ biến để bị bỏ qua, ít nhất là bây giờ.

Tôi đoán độ trễ tối đa phải dưới 50 Patricksec trong 9600 baud để không gặp lỗi và bất kỳ độ trễ nào trên 100 Lời nói gây ra hoàn toàn thiếu một chút trong việc truyền hoặc nhận.

Đây là tất cả mà không cần chạm vào chân GPIO. Vì tôi không thể chạy sạch ngay cả chỉ sau 2 giây, có vẻ an toàn khi nói rằng nếu không có bản vá thời gian thực, Raspberry Pi không thể đập liên kết nối tiếp 9600 baud mà không gây ra lỗi trong bất kỳ khoảng thời gian nghiêm trọng nào.

Tôi sẽ kiểm tra các bản vá thời gian thực sau nếu tôi có thời gian.

(Công cụ được sử dụng: http://git.kernel.org/?p=linux/kernel/git/clrkwllms/rt-tests.git;a=summary )

Cập nhật: Hạt nhân RPi bị treo khi khởi động mà không phát hiện thẻ SD nếu được biên dịch với bộ bản vá CONFIG_PREEMPT_RT. Nó có thể là một điều đơn giản để khắc phục, nhưng nhìn thấy sự khác biệt lộn xộn trong nguồn RPi, tôi nghĩ rằng tôi muốn đợi cho đến khi có nhiều hơn trong nhân chính.

Vì vậy, kiểm tra điều này là quá khó, và tôi đang từ bỏ nó.


0

Bạn không cần phải đập một chút. Bạn có thể thiết lập ngắt đất người dùng trong rx gpio để phát hiện sự sụp đổ của bit start. sau đó đặt ngắt thời gian để lấy mẫu ở giữa các bit. Một mô-đun hạt nhân làm điều đó là khả thi.


Nhưng đó vẫn là một chút đập. Quả thực đó là cách bạn thường làm một chút đập.
Phi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.