Raspberry Pi สามารถเชื่อถือได้ bit bang เป็น 9600 baud serial และมีโค้ดตัวอย่างหรือไม่?


29

ฉันสงสัยว่ามันเป็นไปได้อย่างไรที่จะใช้ bitbanging เพื่อขับ 9600 baud serial ผ่าน GPIO pin บน Raspberry Pi

เห็นได้ชัดว่า Linux ไม่ใช่แพลตฟอร์มที่ดีมากสำหรับการสร้างบิตเนื่องจากมีไดรเวอร์จำนวนมากและการขัดจังหวะอื่น ๆ ซึ่งอาจบล็อก CPU เป็นระยะเวลานาน (1-10ms) อย่างไรก็ตามสถานการณ์ได้ดีขึ้นมากเมื่อเร็ว ๆ นี้และ pre-emption บางอย่างถูกเปิดใช้งานเป็นประจำในเมล็ด ฉันยังสงสัยว่าเคอร์เนลที่ได้รับการปรับปรุงตามเวลาจริงสามารถใช้กับ Raspberry Pi ได้อย่างง่ายดายและสามารถเลือกฮาร์ดแวร์และไดรเวอร์ที่เชื่อมต่อได้อย่างระมัดระวัง

มาตรฐานความน่าเชื่อถือของฉันคือควรอยู่ในช่วงความคลาดเคลื่อนอนุกรมปกติ 9600 บอดเป็นส่วนใหญ่ ขณะนี้ฉันไม่แน่ใจว่ามีข้อผิดพลาดจำนวนเท่าใดที่สามารถใช้ได้ในทางปฏิบัติ แต่มีการส่งสัญญาณซ้ำและการตอบรับในโปรโตคอลดังนั้นจึงค่อนข้างทนได้

ดังนั้นคำถามของฉันคือ:

  • ซอฟต์แวร์ userland สามารถเชื่อถือได้ bit-bang 9600 baud speed หรือไม่?
  • สิ่งนี้ต้องการเคอร์เนลที่ถูกแก้ไขตามเวลาจริงหรือไม่?
  • ฉันควรคาดหวังข้อผิดพลาดกี่ข้อโดยทั่วไป

นอกจากนี้ยังมีรหัสตัวอย่างใด ๆ ที่ทำซีเรียลผ่าน GPIO Bit Banging ฉันรู้จัก Arduino SoftSerial แต่มันเกี่ยวกับมัน

ในกรณีที่ต้องการ จำกัด คำถาม: นี่ไม่ใช่อินเทอร์เฟซแบบอนุกรมมาตรฐานและ UART ของ Raspberry Pi ใช้สำหรับลิงค์อนุกรมอื่นแล้ว ฉันไม่ต้องการคำตอบที่แนะนำฮาร์ดแวร์ภายนอก (เช่น Gertboard หรือ Arduino) หรือคำตอบที่ขึ้นอยู่กับ UART


1
+1 คำถามที่ดี ฉันยังสนใจที่จะตอบคำถามนี้ อย่างไรก็ตามคำถามreliabilityอาจขึ้นอยู่กับการกระทำและความคาดหวัง
Jivings

2
RS-232 ต้องการแรงดันไฟฟ้าลบ แต่ลิงค์อนุกรมนี้ไม่ใช้แรงดันไฟฟ้า RS-232 ฉันไม่รู้ แต่ฉันเชื่อว่า RPi ต้องการตัวแปลง TTL เป็น RS-232 มาตรฐานเช่น MAX232 หรือตัวเลือกอื่น ๆ อีกมากมาย อย่างไรก็ตามเพื่อให้ชัดเจนนี่ไม่เกี่ยวข้องกับคำถามของฉันฉันแค่อยากตอบ
Nakedible

4
มี UART ตัวที่สองใน GPIO พิน 14 และ 15 เช่นกัน มันยังไม่เด่นเท่าที่ควร
John La Rooy


1
@Nakedible คุณช่วยแบ่งปันงานของคุณได้ไหม? ฉันมีปัญหาที่คล้ายกันและต้องการที่จะดูว่าคุณได้อนุกรมที่สองผ่าน spi ขอบคุณ MSP

คำตอบ:


15

ในที่สุดฉันก็แก้ปัญหานี้ แต่ในทางที่ผิดนอกรีต ฉันละทิ้งการต่อสู้ด้วยบิตที่ไม่น่าเชื่อถือและพยายามหาวิธีแก้ปัญหาอื่น ๆ ซึ่งจะทำให้ฉันมีสิ่งเดียวกันโดยไม่ต้องเพิ่มฮาร์ดแวร์เพิ่มเติม ฉันกำลังพิจารณาที่จะเขียนไดรเวอร์เคอร์เนลซึ่งจะทำให้การขัดจังหวะบน GPIO แล้วกำหนดค่าพินใหม่ให้เป็น SPI และใช้ SPI เพื่ออ่านไบต์ข้อมูลทั้งหมด - แต่จากนั้นฉันก็มีความคิดที่ดีขึ้น

ฉันใช้ SPI เพื่อสุ่มเส้นที่อัตราการรับส่งข้อมูลที่ 20x ฉันไม่สนใจพิน SCLK และ SS ทั้งหมดเชื่อมต่อสาย RX กับ MISO และบรรทัด TX กับ MOSI สิ่งนี้ทำให้ฉันมีลักษณะคล้ายออสซิลโลสโคป (1 บิต) ในสาย RX และเห็นชัดเจนว่าบิตที่ถูกส่งในสายอนุกรม:

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 

จากนี้มันเป็นเรื่องง่ายของการเข้ารหัสเพื่อหาตำแหน่งที่ถูกต้องที่จะสุ่มตัวอย่างบิตข้อมูลจริง ด้านการส่งนั้นมีความสำคัญไม่แพ้กันผมเพียงแค่ต้องแปลงทุกไบต์เป็นบิตขนาดยาวด้วยบิตเริ่มต้นและบิตหยุด

เหตุผลนี้ใช้งานได้ดีกว่าการโจมตีด้วยบิตคือ SPI มีนาฬิกาของตัวเองที่ไม่ตรึงกับเคอร์เนลและ SPI ส่งและรับสายมี 16 FIFO สำหรับการถ่ายโอนซึ่งเป็นอิสระจากเคอร์เนลค้าง สำหรับ 9600 baud ฉันใช้นาฬิกา 250kHz SPI และนั่นหมายความว่าฉันสามารถนอนหลับได้แม้กระทั่งมิลลิวินาทีระหว่างการเติมและการระบาย FIFOs โดยไม่มีข้อผิดพลาดในการส่ง อย่างไรก็ตามเพื่อความผิดพลาดในด้านความปลอดภัยฉันใช้สลีป 300 วินาที ฉันทดสอบสั้น ๆ ว่าฉันสามารถผลักดันสิ่งนี้ไปได้อย่างไรและอย่างน้อยที่สุดนาฬิกา SPI ขนาด 2MHz ก็ยังสามารถใช้งานได้ดังนั้นโซลูชันนี้จะปรับอัตราการรับส่งข้อมูลที่สูงขึ้นเช่นกัน

ส่วนที่น่าเกลียดของโซลูชันนี้คือไดรเวอร์ SPI เคอร์เนลไม่รองรับการถ่ายโอนบิตสตรีมมิ่ง ซึ่งหมายความว่าฉันไม่สามารถทำได้โดยการเขียนโมดูลเคอร์เนลของฉันเองโดยใช้ไดรเวอร์เคอร์เนล SPI และฉันยังไม่สามารถทำได้โดยใช้ /dev/sdidev0.0 จากพื้นที่ผู้ใช้ อย่างไรก็ตามใน Raspberry Pi SPI และอุปกรณ์ต่อพ่วงอื่น ๆ สามารถเข้าถึงได้โดยตรงจาก userland โดย mmap (): n / dev / mem โดยไม่ผ่านการควบคุมเคอร์เนลทั้งหมด ฉันไม่ได้มีความสุขอย่างยิ่งกับสิ่งนี้ แต่มันทำงานได้อย่างสมบูรณ์และให้ประโยชน์เพิ่มเติมที่การแบ่งส่วนที่ผิดพลาดใน userland ไม่สามารถชนเคอร์เนลได้ สำหรับการใช้งาน CPU การนอนหลับ 300 ครั้งดูเหมือนจะให้การใช้งาน CPU ประมาณ 7% ต่อเนื่อง แต่รหัสของฉันไม่ดีนัก การเพิ่มระยะเวลาสลีปลดการใช้ CPU โดยตรงอย่างเห็นได้ชัด

แก้ไข: ลืมพูดถึงฉันใช้ไลบรารีbcm2835 ที่ดีในการควบคุม SPI จาก userland โดยขยายออกเมื่อจำเป็น

ดังนั้นเพื่อสรุป: ฉันสามารถส่งและรับได้บนลิงก์อนุกรม 9600 baud ทั้งหมดจาก userland โดยตรงโดยใช้ชิป SPI ผ่าน / dev / mem ที่ 250kHz บน Raspberry Pi


@ Nakedible - คุณสามารถอธิบายรายละเอียดเล็กน้อยหรือจัดเตรียมลิงก์ในส่วน mmap () ฉันกำลังทำงานในสิ่งเดียวกัน
Jay K

คุณใช้ฮาร์ดแวร์ SPI เพื่อทำการส่งด้วยหรือไม่
Cheetah

ใช่การส่งสัญญาณก็ใช้ได้เช่นกัน
Nakedible

3
คุณช่วยกรุณาให้คำแนะนำทีละขั้นตอนวิธีการที่คุณสามารถส่งและรับรหัสและแบ่งปันแพคเกจการแก้ไขใด ๆ ถ้าคุณใช้สิ่งที่คุณแพทช์ตัวเอง ... TIA!
valentt

10

ดูเหมือนว่าอย่างน้อยที่สุดหากไม่มี patch แบบเรียลไทม์ (CONFIG_PREEMPT_RT) Raspberry Pi ไม่สามารถเชื่อถือได้บิตแบ็คแบบอนุกรม 9600 baud อย่างน่าเชื่อถือ

ฉันใช้เครื่องมือทดสอบเวลาแฝงอย่างง่ายซึ่งกำหนดค่าทุกอย่างของ linux ให้เหมาะสมที่สุด (sched_fifo, ลำดับความสำคัญ 99, cpu_dma_latench 0us, mlockall) ฉันลองนอนเป็นเวลา 100 µsec (ประมาณ 9600 baud) และตรวจสอบความหน่วงแฝงบนระบบที่เงียบเป็นเวลา 2 นาที ผลการวิจัยพบว่า:

ต่ำสุด: 12 µsec เฉลี่ย: 24 µsec สูงสุด: 282 µsec

ดูเหมือนว่าผลลัพธ์ทั่วไป ค่าสูงสุดต่างกันไปในการวัดช้าลงระหว่าง 100 µsec และ 300 ecsec ฉันยังตรวจสอบการกระจายและดูเหมือนว่าส่วนใหญ่อยู่ในช่วง 24 µsec มีเพียงไม่กี่ที่ที่สูงกว่า 50 ecsec แต่มีเกือบทุกที่ บางครั้งอาจมีความล่าช้ามากเช่น 4000 ecsec แต่สิ่งเหล่านี้ไม่ธรรมดาพอที่จะถูกเพิกเฉยได้อย่างน้อยตอนนี้

ฉันเดาว่าเวลาแฝงสูงสุดควรต่ำกว่า 50 ecsec สำหรับ 9600 baud เพื่อไม่ให้เกิดข้อผิดพลาดและเวลาแฝงที่มีมากกว่า 100 µsec ทำให้ขาดหายไปเล็กน้อยในการส่งหรือรับสัญญาณ

ทั้งหมดนี้ไม่ได้สัมผัสแม้แต่พิน GPIO เลย เนื่องจากฉันไม่สามารถวิ่งได้อย่างราบรื่นแม้เพียง 2 วินาทีดูเหมือนว่าปลอดภัยที่จะบอกว่าหากไม่มีแพทช์เรียลไทม์ Raspberry Pi ก็ไม่สามารถบิตลิงก์อนุกรม 9600 baud ได้โดยไม่เกิดข้อผิดพลาดในช่วงเวลาที่ร้ายแรง

ฉันจะทำการทดสอบแพตช์แบบเรียลไทม์ในภายหลังหากฉันได้รับเวลา

(เครื่องมือที่ใช้: http://git.kernel.org/?p=linux/kernel/git/clrkwllms/rt-tests.git;a=s บทสรุป )

อัปเดต: เคอร์เนล RPi แฮงค์ขณะบู๊ตโดยไม่ตรวจพบการ์ด SD ถ้าคอมไพล์ด้วยชุดแพตช์ CONFIG_PREEMPT_RT อาจเป็นเรื่องง่าย ๆ ในการแก้ไข แต่การเห็นความยุ่งเหยิงของแหล่ง RPi นั้นแตกต่างกันฉันคิดว่าฉันต้องการรอจนกระทั่งมีมากขึ้นในเคอร์เนลที่ฉีด

ดังนั้นการทดสอบนี้ยากเกินไปและฉันจะละทิ้ง


0

คุณไม่จำเป็นต้องกัดปัง คุณสามารถตั้งค่าการขัดจังหวะโดยผู้ใช้ใน rx gpio เพื่อตรวจจับการเริ่มต้นของบิต จากนั้นตั้งค่าการขัดจังหวะเวลาเพื่อสุ่มตัวอย่างที่ตรงกลางของบิต โมดูลเคอร์เนลทำสิ่งที่เป็นไปได้


แต่นั่นยังคงเป็นการต่อสู้เล็กน้อย แน่นอนว่าเป็นวิธีที่คุณมักจะทำการตบเบา ๆ
Philippos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.