다음 코드를 실행하는 마이크로 컨트롤러가 제공됩니다.
volatile bool has_flag = false;
void interrupt(void) //called when an interrupt is received
{
clear_interrupt_flag(); //clear interrupt flag
has_flag = true; //signal that we have an interrupt to process
}
int main()
{
while(1)
{
if(has_flag) //if we had an interrupt
{
has_flag = false; //clear the interrupt flag
process(); //process the interrupt
}
else
sleep(); //place the micro to sleep
}
}
if(has_flag)
조건이 거짓으로 평가되고 수면 명령을 실행하려고 한다고 가정합니다 . 오른쪽 우리가 잠 명령을 실행하기 전에, 우리는 인터럽트를받을 수 있습니다. 인터럽트를 떠난 후 휴면 명령을 실행합니다.
이 실행 순서는 다음과 같은 이유로 바람직하지 않습니다.
- 마이크로 컨트롤러가 깨어나서 호출하는 대신 절전 모드로 전환되었습니다
process()
. - 이후에 인터럽트가 수신되지 않으면 마이크로 컨트롤러가 깨어날 수 없습니다.
process()
다음 인터럽트까지 호출 이 연기됩니다.
이 경쟁 조건이 발생하지 않도록 코드를 작성하는 방법은 무엇입니까?
편집하다
ATMega와 같은 일부 마이크로 컨트롤러는 이러한 상태가 발생하지 않도록하는 슬립 활성화 비트를 가지고 있습니다 (Kvegaoro가이를 지적 해 주셔서 감사합니다). JRoberts는이 동작을 보여주는 구현 예제를 제공합니다.
PIC18과 같은 다른 마이크로에는이 비트가 없으며 여전히 문제가 발생합니다. 그러나 이러한 마이크로는 전역 인터럽트 활성화 비트가 설정되어 있는지 여부에 관계없이 인터럽트가 코어를 깨울 수 있도록 설계되었습니다 (이 점을 지적 해 주셔서 감사합니다). 이러한 아키텍처의 경우 해결책은 휴면 직전에 글로벌 인터럽트를 비활성화하는 것입니다. 슬립 명령을 실행하기 직전에 인터럽트가 발생하면 인터럽트 핸들러가 실행되지 않고 코어가 깨어나고 글로벌 인터럽트가 다시 활성화되면 인터럽트 핸들러가 실행됩니다. 의사 코드에서 구현은 다음과 같습니다.
int main()
{
while(1)
{
//clear global interrupt enable bit.
//if the flag tested below is not set, then we enter
//sleep with the global interrupt bit cleared, which is
//the intended behavior.
disable_global_interrupts();
if(has_flag) //if we had an interrupt
{
has_flag = false; //clear the interrupt flag
enable_global_interrupts(); //set global interrupt enable bit.
process(); //process the interrupt
}
else
sleep(); //place the micro to sleep
}
}
interrupt_flag
int로서 int
, 그리고 그것을 인터럽트가 때마다 증가. 그런 다음 변경 if(has_flag)
을 while (interrupts_count)
한 후 잠을. 그럼에도 불구하고 while 루프를 종료 한 후에 인터럽트가 발생할 수 있습니다. 이것이 문제라면 인터럽트 자체에서 처리합니까?