2014-06-23 5 views
1

저는 Atmel의 XMEGA 장치 용으로 작은 Zigbee 라이브러리를 구현하고 있습니다. 지그비 (Zigbee) 라디오는 내부 USART를 사용하여 MCU와 통신합니다.순환 버퍼 구문 분석

라이브러리를 작성하기 시작할 때 고정 된 배열과 수신 된 데이터에 대한 인터럽트를 사용했습니다. 지그비가 프레임 길이를 알기 때문에 전체 커맨드를 얻었 으면 (마지막으로 시작 구분자와 체크섬을 뺀) 인터럽트 서비스 루틴에서 플래그를 설정하고 배열을 다른 배열로 복사합니다. 내 주요().

배열을 복사 한 후에 다른 루틴 ZBProcessFrame이 프레임을 파싱하고 적절한 조치를 취합니다.

이 접근법의 잠재적 인 문제는 배열을 복사하는 동안 다른 메시지가 올 수 있으며이 공유 변수를 변경할 수 있다는 것입니다.

온라인으로 읽는다면 어레이를 복사하는 동안 인터럽트를 끌 수도 있고 순환 버퍼를 사용해야한다는 것입니다. 그러면 어레이 전체를 복사하지 않아도됩니다. 32 바이트 순환 버퍼를 성공적으로 구현했지만 이제는 실제 데이터가 시작된 위치와 시작 구분 기호 이후의 바이트 수를 어떻게 알 수 있습니까?

ISR(Receiver Interrupt) 
{ 
    ring->add(USART_Data); 
} 

나는 구분 기호 여기부터 확인하고 유효한 명령이 여기에있다 넣다 플래그를 설정해야 : 내 ISR은 다음있다? 그런 다음 main()은 플래그를 계속 볼 수 있고 발생하면 유효한 명령이 있다는 것을 의미합니다.

이 방법이 유효한 방법입니까 아니면 대안을 찾아야합니까?

답변

4

원형에게 (원형 버퍼를 판독 할 때, 오직 메인 버퍼에 복사 검사 오류 없음) 버퍼는 좋은 디자인입니다. ISR은 가능한 한 간단하게 남겨 두었습니다.main이 수퍼 루프 인 경우 ZBReceiveFrame과 같은 새 루틴에 대한 호출을 추가하여 링 버퍼에서 다음 사용 가능한 바이트 (사용 가능한 모든 바이트까지 개별적으로)를 읽은 다음 상태 시스템에서 처리합니다. 예를 들어, 첫 번째 상태는 프레임 시작 구분 기호를 예상하고 수신되면 다음 상태로 진행합니다. 다음 상태는 프레임 길이를 수신하고 해석합니다. 다음 상태는 프레임 본문을 수신하고 최종 상태는 프레임 CRC (모든 예제)의 유효성을 검사합니다. 스위치 문을 사용하여 상태를 모두 ZBReceiveFrame 내에 구현할 수 있습니다. ZBReceiveFrame 안에 사용 된 상태 변수는 하나의 호출에서 다음 호출로 상태가 기억 될 수 있도록 정적이어야합니다. 최종 상태가 유효한 프레임을 식별하면 mainZBProcessFrame을 호출하도록 플래그를 설정합니다. ZBReceiveFrame이 하나 또는 모든 사용 가능한 문자를 처리할지 여부는 수퍼 루프의 다른 시간이 얼마나 중요한지에 따라 다릅니다.

이 기술은 loose coupling을 생성하므로 바람직합니다. ISR은 바이트를 링 버퍼로 수신 할 책임이 있으며 프레임이 무엇인지에 대해 알지 못합니다. ZBReceiveFrame은 링 버퍼에서 읽는 방법과 프레임을 구분하는 방법 만 알고 있지만 데이터 해석 방법을 알지 못합니다. ZBProcessFrame은 프레임 내의 데이터를 해석하지만 링 버퍼에 대한 지식이 없습니다.

1

순환 버퍼에는 읽기 및 쓰기 위치가 있어야합니다. WR은 다음 빈 공간을 지시하고 RD는 가장 오래된 수신 바이트를 가리 킵니다.

그러나 이것은 동시에 두 변수를 조작해야한다는 것을 의미합니다. 예를 들어 RD가 WR을 초과해서는 안됩니다. 그리고 당신은 하나의 명령으로 이것을 할 수 없으므로 어느 하나가 읽혀 지거나 쓰여질 때 인터럽트를 비활성화해야합니다. 나는 보통 이런 식으로했을

는 :

  • 은 인터럽트 루틴에서 사용되는 putByte 기능을 가지고. ISR에서 수행 한 작업은 없습니다.

  • 주 프로그램에서 사용되는 getByte 기능이 있어야합니다. 이 기능은 일시적으로 인터럽트를 비활성화합니다. 버퍼가 비어있는 경우 특별 값 (-1 또는 유사)을 반환합니다.

  • 각 주 루프 반복에서 순환 버퍼에서 주 버퍼로 사용 가능한 바이트를 복사합니다. 순환 버퍼가 비어 있거나 주 버퍼가 가득차면 수신 된 데이터를 확인하십시오. 충분한 바이트가 없으면 다음 메인 루프 반복에서 더 많이 복사하십시오. 그렇지 않으면 프로세스 프레임. ISR에서

시간 (에만 원형 버퍼 바이트 복사) 짧아야, 시간 블로킹 ISR은 짧아야

+2

여기에 속임수가 없습니다. 단 하나의 리더와 하나의 작성자 (ISR 일 가능성이 있음)를 제공하면 소비자의 ISR 및 RP에 WP 만 쓸 필요가 없으므로 잠재적 경쟁 조건이 발생할 수 있습니다. 이 배열은 잠금없는 순환 버퍼를 생성합니다. SMP 시스템이나 CPU가 주문에 맞지 않는 명령을 사용하는 경우에는 메모리 장벽을 사용해야합니다. – marko

+0

@marko 그게 내가하는 일이야. – saad

+0

아니요. 버퍼에서 바이트를 읽을 때 인터럽트를 비활성화한다고 가정 해보십시오. 당신은 이것을 할 필요가 없습니다. – marko