Должен ли я получить данные SPI в режиме прерывания? - PullRequest
0 голосов
/ 11 января 2019

Я использую esp32 как мастер spi с 24-битным АЦП, который использует SPI для передачи данных. АЦП указывает, что новый образец готов к извлечению путем понижения вывода IO, подключенного к esp32. Должна ли эта транзакция SPI выполняться непосредственно в обработчике прерываний gpio или в основном цикле? Я думал о том, чтобы просто установить флаг в обработчике прерываний, чтобы указать, что новый образец готов, а затем постоянно проверять этот флаг в основном цикле. Вот как я делал это раньше, потому что всегда опасался, что процедуры прерывания занимают слишком много времени.

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Вы должны делать как можно меньше в обработчике прерываний. Это в целом верно независимо от используемой платформы или ОС.

Код уровня без прерываний должен блокировать прерывания, чтобы гарантировать, что обработчикам прерываний не мешают структуры данных и ввод / вывод.

Например, в вашем случае вы спросили, следует ли инициировать транзакцию SPI в обработчике прерываний. Если вы сделаете это, для безопасности вам нужно убедиться, что где бы вы ни использовали SPI вне обработчика прерываний, он блокирует прерывания. В противном случае возможно возникновение противоречивого состояния в библиотеке SPI или на оборудовании, к которому вы обращаетесь через SPI, если происходит прерывание и вы вызываете библиотеку SPI, когда она также выполняется вне обработчика прерываний.

То же самое относится и к структурам данных. Предположим, вы храните связанный список, который вы используете вне обработчика прерываний, и добавляете в него что-то внутри обработчика прерываний. Если прерывание происходит не вовремя, вы повредите структуру списка, если только не заблокируете прерывания, когда манипулируете или пересекаете его.

Вы хотите минимизировать время, в течение которого вы блокируете прерывания - блокировка их может повлиять на время и привести к потере данных.

Это означает, что вам лучше, если вы выполняете наименьшую возможную работу в обработчике прерываний. Тогда вам не нужно блокировать прерывания вне его, и вы не будете пропускать прерывания или отбрасывать данные, и вы также не рискуете повредить структуры данных или перевести оборудование ввода-вывода в несогласованное состояние, если вы забудьте заблокировать прерывания в важной части вашего кода.

Обычно мы используем простую переменную, называемую «семафор», чтобы указать, что произошло прерывание. Обработчик прерываний может увеличивать семафор, а код обработки уровня без прерываний может уменьшать его. Пока компилятор может управлять семафором в одной инструкции, он будет защищен от повреждения.

В C нам нужно объявить переменную семафора как volatile, что позволяет компилятору C знать, что она может измениться в любое время. Затем компилятор генерирует код, который не зависит от значения переменной, которое остается неизменным между операциями.

volatile int got_interrupt = 0;

Обработчик прерываний просто увеличивает got_interrupt, а код, выполняющийся вне обработчика прерываний, проверяет его и, если он не равен нулю, уменьшает его и выполняет любые необходимые действия (в вашем случае вызовите SPI библиотека).

0 голосов
/ 12 января 2019

Поскольку вы используете freeRTOS, у вас должна быть задача, которая считывает данные из АЦП. Процедура прерывания должна только уведомить (наиболее эффективный способ - использовать прямые уведомления о задачах) задачу считывателя. Так что ни один из ваших подходов в этом случае не верен.

...