Dzisiaj zajmę się poprawną obsługą oczekiwania na przerwanie, jeśli przerwania oparte są na poll (czyli biblioteka WiringPi i klony).
W czym jest problem?
Otóż poll chodzi sobie w drugim wątku. Jest to metoda nie obciążająca procesora. Samo poll nie zużywa mocy obliczeniowej. Natomiast większość przykładów, które widziałem, oparte są na pętli nieskończonej, oczekującej na wystąpienie przerwania. Co powoduje, że ta pętla obciąża nam procesor w 100%.
Przykład takiego użycia:

 C++ | 
 
 copy code |
?

01
bool packetAvailable = false;         
02
 
03
void signalsInterrupt(void) 
04
{
05
	packetAvailable = true;
06
}
07
 
08
int main(int argc, char *argv[])
09
{
10
	wiringPiSetup();
11
 
12
	pinMode(GDO2, INPUT);
13
	pullUpDnControl(GDO2, PUD_UP);
14
 
15
	wiringPiISR(GDO2, INT_EDGE_FALLING, &signalsInterrupt);
16
 
17
	while (1)
18
	{
19
		if (packetAvailable) 
20
		{
21
			(...)
22
		}
23
	}
24
 
25
	return 0;
26
}

Mało eleganckie, nieprawdaż?
Z pomocą przychodzą nam mechanizmy do obsługi wątków, jak np. semafory.
A oto poprawny przykład, zużywający ~0% procesora:

 C++ | 
 
 copy code |
?

01
static sem_t interrupt;
02
 
03
void signalsInterrupt(void) 
04
{
05
	sem_post(&interrupt);
06
}
07
 
08
int main(int argc, char *argv[])
09
{
10
	wiringPiSetup();
11
 
12
	pinMode(GDO2, INPUT);
13
	pullUpDnControl(GDO2, PUD_UP);
14
 
15
	sem_init(&interrupt, 0, 0);
16
	wiringPiISR(GDO2, INT_EDGE_FALLING, &signalsInterrupt);
17
 
18
	while (1)
19
	{
20
		sem_wait(&interrupt);
21
 
22
		(...)
23
	}
24
 
25
	return 0;
26
}

Kod działa następująco. sem_init definiuje nam semafor obsługujący przerwanie. Callback signalsInterrupt wywoływany jest przez wątek obsługujący przerwanie (ten z poll). Tutaj ustawiany jest semafor. W pętli głównej while(1) oczekujemy na ustawienie semafora. Wszystko bez zużycia procesora.