Вы должны делать как можно меньше в обработчике прерываний. Это в целом верно независимо от используемой платформы или ОС.
Код уровня без прерываний должен блокировать прерывания, чтобы гарантировать, что обработчикам прерываний не мешают структуры данных и ввод / вывод.
Например, в вашем случае вы спросили, следует ли инициировать транзакцию SPI в обработчике прерываний. Если вы сделаете это, для безопасности вам нужно убедиться, что где бы вы ни использовали SPI вне обработчика прерываний, он блокирует прерывания. В противном случае возможно возникновение противоречивого состояния в библиотеке SPI или на оборудовании, к которому вы обращаетесь через SPI, если происходит прерывание и вы вызываете библиотеку SPI, когда она также выполняется вне обработчика прерываний.
То же самое относится и к структурам данных. Предположим, вы храните связанный список, который вы используете вне обработчика прерываний, и добавляете в него что-то внутри обработчика прерываний. Если прерывание происходит не вовремя, вы повредите структуру списка, если только не заблокируете прерывания, когда манипулируете или пересекаете его.
Вы хотите минимизировать время, в течение которого вы блокируете прерывания - блокировка их может повлиять на время и привести к потере данных.
Это означает, что вам лучше, если вы выполняете наименьшую возможную работу в обработчике прерываний. Тогда вам не нужно блокировать прерывания вне его, и вы не будете пропускать прерывания или отбрасывать данные, и вы также не рискуете повредить структуры данных или перевести оборудование ввода-вывода в несогласованное состояние, если вы забудьте заблокировать прерывания в важной части вашего кода.
Обычно мы используем простую переменную, называемую «семафор», чтобы указать, что произошло прерывание. Обработчик прерываний может увеличивать семафор, а код обработки уровня без прерываний может уменьшать его. Пока компилятор может управлять семафором в одной инструкции, он будет защищен от повреждения.
В C нам нужно объявить переменную семафора как volatile
, что позволяет компилятору C знать, что она может измениться в любое время. Затем компилятор генерирует код, который не зависит от значения переменной, которое остается неизменным между операциями.
volatile int got_interrupt = 0;
Обработчик прерываний просто увеличивает got_interrupt
, а код, выполняющийся вне обработчика прерываний, проверяет его и, если он не равен нулю, уменьшает его и выполняет любые необходимые действия (в вашем случае вызовите SPI библиотека).