2014-09-07 2 views
2

현재 ATmega32u4를 프로그래밍 중입니다. Rx 핀에 수신 된 바이트가있을 때마다 실행되는 인터럽트 빌드를 사용하여 구현되는 직렬 통신을 구현했습니다. Rx 핀의 바이트는 Rx 핀에서 다른 바이트가 수신 될 때 대체되는 1 바이트 버퍼에 배치됩니다. 이것은 atmel에 내장 된 라이브러리입니다.AVR8 실시간 스케줄러, 시리얼 통신

ISR(USART1_RX_vect, ISR_BLOCK) 
{ 
    RingBuffer_Insert(&usart_rx_buffer,UDR1); 
} 

내 코드는 바이트가 Rx 핀에서 수신 될 때 인터럽트를 실행합니다. 바이트가 수신되면이 바이트는 링 버퍼 uart_rx_buffer에 입력되어 나중에 디코딩됩니다.

인터럽트가 실행 중이고 UART 인터럽트를 실행하기 전에 1 바이트 버퍼를 교체하면이 바이트가 손실됩니다.

이 결과는 다른 인터럽트가 전송 속도보다 오래 걸릴 수 없다는 것입니다. 그렇지 않으면 직렬 바이트가 손실됩니다.이 문제를 방지 할 수있는 방법이 있습니까? 이 문제를 해결하기

답변

2

한 가지 방법은 ISR 내에서 가능한 한 빨리 컴파일러에 의해 활성화 될 수 있도록 인터럽트 플래그를 유발하고 수, 전송 속도보다 오래 걸릴 모든 인터럽트의 속성을 ISR_NOBLOCK를 사용하는 것 USART1_RX_vect은 다른 인터럽트 내부에서 실행됩니다. 그러나 "스택 오버플로를 방지하거나 AVR 하드웨어가 ISR에 들어가기 전에 해당 인터럽트 플래그를 지우지 않는 경우 ISR에 무한하게 들어가는 것을 피하기 위해주의를 기울여야합니다".

나는이 동일한 문제를 경험했으며 지금까지 이것이 내가 생각할 수있는 최상의 해결책이었다. 나는 그것을 사용하지도 않았고 테스트도했다..

편집 : 명심 다른 모든 인터럽트는 내부 실행 될 수있는 속성 ISR_NOBLOCK, 당신이 원하는뿐만 아니라 인터럽트로 선언 인터럽트. 따라서 기본적으로 모든 인터럽트가 USART1_RX_vect (및 으로 선언 된 인터럽트 ISR_BLOCK)을 제외한 모든 인터럽트에 중첩되도록 허용합니다. 이 문제는 스택 오버플로 문제 외에도이 솔루션의 주된 문제입니다.

1

결과적으로 다른 인터럽트는 전송 속도보다 오래 걸릴 수 없기 때문에 직렬 바이트가 손실됩니다. 이 문제를 피할 수있는 방법이 있습니까?

귀하의 모든 의견이 올바른 것입니다. Nuno의 답변에서 제안 된 것과 같이 중첩 된 인터럽트를 허용하는 것은 일반적으로 사용자가 피하고 싶거나 피해야 할 대상입니다. 모든 곳에서 중첩 된 인터럽트를 허용하면 코드를 예측할 수 없게 만듭니다.

먼저 UART 수신 ISR을 차단하는 인터럽트의 실행 시간을 최적화하려고합니다. 인터럽트 우선 순위를 살펴보십시오. 보류중인 인터럽트가 여러 개인 경우이 우선 순위에 따라 실행됩니다. 이것은 보류중인 상위 레벨 인터럽트가 항상 "항상"있는 경우 하위 인터럽트의 "기아 상태"를 초래할 수 있습니다.

전송 속도는 무엇입니까? 115200 비트/s조차도 수신 된 바이트 당 약 700 개의 명령어 (8MHz라고 가정)를 실행할 수 있습니다. ISR은 가능한 한 짧아야합니다. 하나의 단일 ISR이 오래 걸리고 어떤 이유로 든 최적화 할 수없는 경우이 단일 ISR에서 중첩 된 인터럽트를 허용하는 것을 고려할 수 있습니다 (이는 실행이 중요하지 않은 경우에만 가능합니다).

높은 전송 속도를 사용하는 경우 전송 속도를 줄이는 것이 좋습니다. 9600 보드 만 있으면 충분하지만 코드를 차단하지 않도록 비동기 전송이 필요할 수 있습니다.

+0

인터럽트 컨텍스트에서 작업을 수행하면 안되는 긴 인터럽트의 실행이 중요하지 않은 경우. 이 경우 ISR은 주 루프에서 처리되는 플래그 만 설정해야합니다. –