Ahududu Pi güvenilir bir 9600 baud seri bit ısırdırabilir ve örnek kod var mı?


29

Raspberry Pi'deki GPIO pinleri aracılığıyla 9600 baud'luk bir seriyi sürmek için bitbanging kullanmanın ne kadar mümkün olduğunu merak ediyorum.

Açıkçası, Linux bitbanging için çok iyi bir platform değil, çünkü CPU'yu uzun süre (1-10 ms) engelleyebilecek çok sayıda sürücü ve diğer kesintiler var. Bununla birlikte, son zamanlarda durum çok daha iyi bir hale geldi ve artık bazı ön hazırlıklar artık düzenli olarak çekirdeklerde etkin hale getiriliyor. Ayrıca Raspberry Pi'de gerçek zamanlı yamalı çekirdeğin kolayca kullanılabileceğinden ve bağlı donanım ve sürücülerin dikkatlice seçildiğinden şüpheleniyorum.

Güvenilirlik standardım, çoğu zaman normal 9600 baud seri toleranslarında kalması gerektiğidir. Şu anda pratikte kaç hataya tolere edilebildiğinden emin değilim, ancak protokolde yeniden iletimler ve onaylar var, bu yüzden en azından biraz toleranslı.

Yani benim sorularım:

  • Userland yazılımı güvenilir bir şekilde 9600 baud hızı ile hızlı bir şekilde çalışabilir mi?
  • Bunun gerçek zamanlı yamalı çekirdeğe ihtiyacı var mı?
  • Genel olarak kaç hata beklemeliyim?

Ayrıca, GPIO biti yoluyla seri hale getirilen herhangi bir örnek kod var mı? Arduino SoftSerial'ü biliyorum, ama bu konuda.

Sadece durumda, soruyu sınırlandırmak için: bu standart bir seri arayüz değil ve Raspberry Pi'nin UART'ı zaten başka bir seri link için kullanılıyor. Dış donanım öneren cevapları (Gertboard veya Arduino gibi) veya UART'a bağlı cevapları istemiyorum.


1
+1 Güzel soru. Bunun cevabını da merak ediyorum. Ancak, sorusu reliabilityeyleme ve beklentilere bağlı olabilir.
Jivings

2
RS-232 negatif voltaj gerektirir, ancak bu seri bağlantı RS-232 voltaj kullanmaz. Bilmiyorum ama RPi'nin MAX232 veya onlarca seçenek arasından herhangi biri gibi standart TTL - RS-232 çevirici gerektirdiğine inanıyorum. Ancak, sadece açık olmak gerekirse, bu sorumla alakalı değil, sadece cevaplamak istedim.
Nakedible

4
GPIO 14 ve 15 pinlerinde de ikinci bir UART var. Gerçi ana özellik olarak tam özellikli değil
John La Rooy


1
@Nakedible işinizi paylaşır mısınız? Benzer bir sorunum var ve spi ile ikinci bir seriyi nasıl yaptığınızı görmek istiyorum. teşekkürler MSP

Yanıtlar:


15

Sonunda bunu çözdüm, ancak oldukça alışılmadık bir şekilde. Güvenilmez bir şekilde bit-banging'i bıraktım ve daha fazla donanım eklemeden aynı şeyi yapmama izin verecek başka çözümler bulmaya çalıştım. GPIO'da bir kesmeyi tetikleyen ve ardından pimi SPI olacak şekilde yeniden yapılandıran ve tüm veri baytını okumak için SPI'yi kullanan bir çekirdek sürücüsü yazmayı düşünüyordum - ama sonra daha iyi bir fikrim var.

SPI'yi hatları 20 kat baud hızında örneklemek için kullanıyorum. SCLK ve SS pinlerini tamamen görmezden gelirim, RX hattını MISO'ya ve TX hattını MOSI'ye bağlayın. Bu bana RX hattında (1-bit) osiloskop benzeri bir görünüm kazandırıyor ve seri hatta iletilen bitleri açıkça görüyor:

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 

Bundan, gerçek veri bitlerinin örnekleneceği doğru pozisyonları bulmak basit bir kodlama meselesidir. Gönderen taraf eşit derecede önemsizdir, sadece her bit'i başlangıç ​​bit ve stop biti içeren uzun bir bit akışına dönüştürmem gerekiyor.

Bunun bit-çarpmadan daha iyi çalışmasının nedeni, SPI'nin çekirdekle donmayan kendi saatine sahip olması ve SPI gönderme ve alma hatlarının, çekirdek donmalarından bağımsız olan transfer için 16 baytlık bir FIFO'ya sahip olmasıdır. 9600 baud için 250kHz SPI saat kullanıyorum ve bu, FIFO'ları herhangi bir iletim hatası olmadan doldurma ve boşaltma arasında bir milisaniyede bile uyuyabileceğim anlamına geliyor. Ancak, güvenli tarafta hata yapmak için, 300 µs sleeps kullanıyorum. Bunu ne kadar zorlayabileceğimi kısaca test ettim ve en azından bir 2MHz SPI saati hala kullanılabiliyordu, bu yüzden bu çözüm de daha yüksek baud oranlarına ölçeklendiriyordu.

Bu çözümün çirkin bir parçası, çekirdek SPI sürücüsünün böyle bir akış bit aktarımını desteklememesidir. Bunun anlamı, çekirdek SPI sürücüsünü kullanarak kendi çekirdek modülümü yazarak yapamayacağım ve ayrıca kullanıcı ülkesinden /dev/sdidev0.0 kullanarak bunu yapamam. Bununla birlikte, Raspberry Pi'de SPI ve diğer çevre birimlerine, mmap (): n / dev / mem, kullanıcı kontrolünden tamamen çekirdeğin kontrolünü atlayarak doğrudan kullanıcı alanından erişilebilir. Bundan çok mutlu değilim, ancak mükemmel çalışıyor ve kullanıcı alanındaki segmentasyon hatalarının çekirdeğe zarar vermeyeceği (diğer çevre birimleriyle kazayla karışmadığı sürece) ek faydası var. CPU kullanımıyla ilgili olarak, 300 µs uyku sürekli bana yaklaşık% 7 CPU kullanımı veriyor gibi görünüyor, ancak kodum çok uygun değil. Uyku süresinin arttırılması açıkça CPU kullanımını doğrudan düşürür.

Düzenleme: Bahsetmeyi unuttum, güzel bcm2835 kütüphanesini SPI'yi kullanıcı alanından kontrol etmek için kullandım, gerektiğinde uzatarak.

Böylece, özetlemek gerekirse: Raspberry Pi'deki 250kHz'de / dev / mem üzerinden SPI yongasını kullanarak doğrudan kullanıcı alanından gelen 9600 baud seri bağlantı üzerinden güvenilir bir şekilde iletebilir ve alabilirim.


@ Nakedible - Biraz detaylandırabilir veya mmap () kısmına link verebilir misiniz? Aynı şey üzerinde çalışıyorum.
Jay K,

İletimi yapmak için SPI donanımını da kullanıyor musunuz?
Çita

Evet, iletim de işe yarıyor.
Nakedible

3
Lütfen, kodunuzu nasıl gönderebileceğiniz ve alabileceğiniz adım adım talimatlar verebilir ve kendiniz yamaladığınız bir şey kullanırsanız değiştirilmiş paketleri paylaşabilirsiniz ... TIA!
valentt

10

Gerçek zamanlı yamalar olmadan en azından (CONFIG_PREEMPT_RT), Ahududu Pi'nin bir 9600 baud seriyi güvenilir bir şekilde çarpturamayacağı anlaşılıyor.

Tüm linux tarafı şeylerini en iyi şekilde ayarlayan basit bir gecikme test cihazı kullandım (sched_fifo, öncelik 99, cpu_dma_latench 0us, mlockall). 100 µs (yaklaşık 9600 baud) uyumaya ve gecikme süresinin sessiz bir sistemde 2 dakika boyunca kontrol edilmesine çalıştım. Sonuçlar şunlardı:

Min: 12 µsec Ort: 24 µsec Max: 282 µsec

Bu ortak sonuç gibi görünüyordu. Maksimum değer, 100 µsec ile 300 µsec arasındaki daha yavaş ölçümlerde değişmiştir. Ayrıca dağılımı kontrol ettim ve büyük çoğunluğun 24 µsec aralığında olduğu görülüyor. 50 50sn üzerine çıkan sadece birkaçı var, fakat neredeyse her zaman bir kısmı var. Bazen 4000 µsn gibi büyük gecikmeler de olabilir, ancak bunlar şimdilik göz ardı edilebilecek kadar nadir görülür.

Sanırım 9600 baud için hata almamak için maksimum gecikmeler 50 µsec'in altında olmalı ve 100 µsec'in üzerindeki herhangi bir gecikme, iletim veya alımda bir miktar tamamen eksikliğe neden olur.

Hepsi henüz GPIO pinlerine dokunmadan bile geliyor. Sadece 2 saniyeyle bile temiz bir koşuya sahip olamadığımdan, gerçek zamanlı yamalar olmadan Raspberry Pi'nin ciddi bir süre boyunca hata üretmeden 9600 baud seri bağlantıya çarpamayacağını söylemek güvenli görünüyor.

Zamanım olursa, gerçek zamanlı yamaları test edeceğim.

(Kullanılan araç: http://git.kernel.org/?p=linux/kernel/git/clrkwllms/rt-tests.git;a=summary )

Güncelleme: RPi çekirdeği, CONFIG_PREEMPT_RT yama seti ile derlenmişse, SD kartı tespit etmeden önyüklemede kilitlenir. Düzeltilmesi basit bir şey olabilir, ancak dağınıklığı RPI kaynağında görmek, ana hat çekirdeğinde olana kadar beklemek istiyorum.

Yani, bunu test etmek çok zor ve ben onu terk ediyorum.


0

Patlamaya ihtiyacın yok. Başlangıç ​​bitinin düşmesini algılamak için rx gpio'da bir kullanıcı arazi kesmesi ayarlayabilirsiniz. daha sonra bitlerin ortasında numuneye bir zaman kesmesi ayarlayın. Bunu yapan bir çekirdek modülü mümkün.


Ama bu hala biraz beceriyor. Gerçekten de, genellikle biraz beceriyorsun.
Philippos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.