Raspberry Pi가 9600 보드 시리얼을 안정적으로 비트 뱅할 수 있으며 예제 코드가 있습니까?


29

비트 뱅킹을 사용하여 Raspberry Pi의 GPIO 핀을 통해 9600 보드 시리얼을 구동하는 것이 얼마나 실현 가능한지 궁금합니다.

분명히 리눅스는 비트 뱅킹을위한 아주 좋은 플랫폼이 아닙니다. 많은 수의 드라이버와 다른 인터럽트가있어 CPU를 장시간 (1-10ms) 차단할 수 있습니다. 그러나 최근 상황이 훨씬 나아졌으며 커널에서 일부 선점권이 정기적으로 활성화되었습니다. 또한 실시간 패치 커널을 Raspberry Pi에서 쉽게 사용할 수 있으며 연결된 하드웨어와 드라이버를 신중하게 선택할 수 있다고 생각합니다.

안정성에 대한 나의 표준은 대부분의 경우 정상적인 9600 보드 직렬 공차 내에 있어야한다는 것입니다. 현재 실제로 허용 가능한 오류 수는 확실하지 않지만 프로토콜에 재전송 및 승인이 있으므로 약간 허용됩니다.

그래서 내 질문은 :

  • 유저 랜드 소프트웨어가 9600 보드 속도를 안정적으로 비트 뱅킹 할 수 있습니까?
  • 실시간 패치 커널이 필요합니까?
  • 일반적으로 몇 개의 오류가 예상됩니까?

또한 GPIO 비트 뱅킹을 통해 시리얼을 수행하는 예제 코드가 있습니까? Arduino SoftSerial에 대해 알고 있지만 그게 전부입니다.

질문을 제한하기 위해 : 이것은 표준 직렬 인터페이스가 아니며 Raspberry Pi의 UART가 이미 다른 직렬 링크에 사용되었습니다. 외부 하드웨어 (예 : Gertboard 또는 Arduino)를 제안하는 답변이나 UART에 의존하는 답변을 원하지 않습니다.


1
+1 좋은 질문입니다. 나는 또한 이것에 대한 답변에 관심이 있습니다. 그러나 의문은 reliability행동과 기대에 달려 있습니다.
Jivings

2
RS-232는 음의 전압이 필요하지만이 직렬 링크는 RS-232 전압을 사용하지 않습니다. 잘 모르겠지만 RPi에는 MAX232 또는 수십 가지 선택과 같은 표준 TTL 대 RS-232 변환기가 필요하다고 생각합니다. 그러나 분명히 말하면, 이것은 내 질문과 관련이 없으며 대답하고 싶었습니다.
Nakedible

4
GPIO 핀 14 & 15에도 두 번째 UART가 있습니다. 그것은으로 전체의 주요 한 것처럼 기능을 갖춘 아니에요
존 라 Rooy


1
@Nakedible 당신은 당신의 작업을 공유 할 수 있습니까? 비슷한 문제가 있으며 spi를 통해 두 번째 시리얼을 어떻게 수행했는지 확인하고 싶습니다. 고마워요 MSP

답변:


15

나는 마침내 이것을 해결했지만 꽤 정통적인 방법으로. 비트 뱅킹을 너무 신뢰할 수 없게 포기하고 더 많은 하드웨어를 추가하지 않고도 같은 일을 할 수있는 다른 솔루션을 찾으려고 노력했습니다. GPIO에서 인터럽트를 트리거하고 핀을 SPI로 재구성하고 SPI를 사용하여 전체 데이터 바이트를 읽는 커널 드라이버 작성을 고려하고 있었지만 더 나은 아이디어를 얻었습니다.

SPI를 사용하여 전송 속도의 20 배로 라인을 샘플링합니다. 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 보드의 경우 250kHz SPI 클럭을 사용하고 있으며 전송 오류없이 FIFO를 채우고 배출하는 사이에 1 밀리 초 동안 절전 모드로 전환 할 수 있습니다. 그러나 안전 측면에서 실수를하기 위해 300µs 절전 모드를 사용하고 있습니다. 나는 이것을 얼마나 멀리 밀어 넣을 수 있는지에 대해 간단히 테스트했으며 2MHz SPI 클럭을 여전히 사용할 수 있었기 때문에이 솔루션은 더 높은 전송 속도로 확장됩니다.

이 솔루션의 한 가지 추악한 부분은 커널 SPI 드라이버가 이러한 스트리밍 비트 전송을 지원하지 않는다는 것입니다. 즉, 커널 SPI 드라이버를 사용하여 자체 커널 모듈을 작성하여이 작업을 수행 할 수 없으며 사용자 랜드에서 /dev/sdidev0.0을 사용하여이 작업을 수행 할 수도 없습니다. 그러나 Raspberry Pi에서 SPI 및 기타 주변 장치는 커널 제어를 완전히 무시하고 mmap () : n / dev / mem을 통해 사용자 영역에서 직접 액세스 할 수 있습니다. 나는 이것에 몹시 만족하지 않지만 완벽하게 작동하며 우연히 다른 주변 장치를 엉망으로 만들지 않는 한 userland의 세그먼테이션 결함으로 인해 커널이 충돌 할 수 없다는 추가 이점을 제공합니다. CPU 사용의 경우 300 µs 휴면으로 인해 CPU 사용률이 약 7 % 인 것으로 보이지만 코드가 매우 적합하지 않습니다. 절전 시간을 늘리면 CPU 사용량이 직접적으로 줄어 듭니다.

편집 : 언급을 잊어 버렸습니다. 좋은 bcm2835 라이브러리를 사용하여 사용자 영역에서 SPI를 제어하고 필요한 곳으로 확장했습니다.

요약하자면 , Raspberry Pi에서 250kHz에서 / dev / mem을 통해 SPI 칩을 직접 사용하여 사용자 영역에서 9600 보드 직렬 링크로 안정적으로 송수신 할 수 있습니다.


@ Nakedible--mmap () 부분을 조금 정교하게하거나 링크를 제공 할 수 있습니까? 나는 똑같은 일을하고 있습니다.
Jay K

전송에도 SPI 하드웨어를 사용하고 있습니까?
치타

예, 전송도 잘 작동합니다.
Nakedible

3
직접 패치 한 것을 사용하는 경우 코드를 보내고받는 방법과 수정 된 패키지를 공유하는 방법에 대한 단계별 지침을 제공 할 수 있습니까?
valentt

10

실시간 패치 (CONFIG_PREEMPT_RT)가 없으면 Raspberry Pi는 9600 보드 시리얼을 안정적으로 비트 뱅할 수 없습니다.

나는 모든 리눅스 측면을 최적으로 구성한 간단한 대기 시간 테스터를 사용했다 (sched_fifo, priority 99, cpu_dma_latench 0us, mlockall). 100µsec (대략 9600 보드) 동안 절전 모드를 시도하고 2 분 동안 조용한 시스템에서 대기 시간이 초과되는지 확인했습니다. 결과는 다음과 같습니다.

최소 : 12 µsec 평균 : 24 µsec 최대 : 282 µsec

이것은 일반적인 결과처럼 보였다. 최대 값은 100µsec와 300µsec 사이의 느린 측정에서 다양했습니다. 또한 분포를 확인했는데 대다수가 24 µsec 범위에있는 것 같습니다. 50 µsec를 초과하는 것은 소수이지만 거의 항상 존재합니다. 때로는 4000 µsec와 같은 거대한 대기 시간이 있지만, 지금까지는 무시할 정도로 흔하지 않습니다.

9600 보드에서 오류가 발생하지 않도록 최대 대기 시간이 50μsec 미만이어야하고 100μsec를 초과하는 대기 시간으로 인해 전송 또는 수신시 비트가 완전히 누락 될 수 있습니다.

아직 GPIO 핀을 건드리지 않아도됩니다. 단 2 초만으로도 깔끔한 실행을 할 수 없었기 때문에 실시간 패치가 없으면 Raspberry Pi가 심각한 시간 동안 오류를 발생시키지 않고 9600 보드 직렬 링크를 비트 뱅할 수 없다고 말하는 것이 안전합니다.

시간이 있으면 나중에 실시간 패치를 테스트 할 것입니다.

(사용 된 도구 : http://git.kernel.org/?p=linux/kernel/git/clrkwllms/rt-tests.git;a=summary )

업데이트 : CONFIG_PREEMPT_RT 패치 세트로 컴파일 된 경우 SD 카드를 감지하지 않고 부팅시 RPi 커널이 정지됩니다. 수정하는 것이 간단 할 수도 있지만 RPi 소스의 지저분한 차이를보고 더 많은 것이 메인 라인 커널에있을 때까지 기다릴 생각입니다.

따라서 이것을 테스트하는 것은 너무 어렵습니다. 나는 그것을 버리고 있습니다.


0

비트 뱅 할 필요가 없습니다. rx gpio에서 사용자 랜드 인터럽트를 설정하여 시작 비트의 하강을 감지 할 수 있습니다. 그런 다음 비트 중간에서 샘플링 할 시간 인터럽트를 설정하십시오. 이를 수행하는 커널 모듈이 가능합니다.


그러나 그것은 여전히 ​​약간 두드리고 있습니다. 실제로 그것은 당신이 일반적으로 비트 뱅을하는 방법입니다.
Philippos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.