2016-10-13 3 views
2

Я начинаю работать с платформой ARM (в частности, с семейством TI TMS570).Временно отключить прерывания на ARM

У меня есть код с критическими областями, где я не хочу, чтобы возникло исключение. Поэтому я хочу сохранить флаги с поддержкой IRQ и FIR при входе в регионы и восстановить их при выходе.

Как это сделать?

ответ

8

Для временного маскирования прерываний и FIQs на CPU, самый хороший вариант для ARMv7 является использование cps:

// assembly code assuming interrupts unmasked on entry 

cpsid if // mask IRQ and FIQ 
...  // do critical stuff 
cpsie if // unmask 

Некоторые компиляторы предоставляют набор __disable_irq() и т.д. использовать встроенные функции из кода C, а для других (как GCC), это будет случай отказа от сборки.

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

// int enter_critical_section(void); 
enter_critical_section: 
mrs r0, cpsr 
cpsid if 
and r0, r0, #0xc0 // leave just the I and F flags 
bx lr 

// void leave_critical_section(int flags); 
leave_critical_section: 
mrs r1, cpsr 
bic r1, r1, r0 
msr cpsr_c, r1 
bx lr 
+0

Спасибо! Выглядит очень хорошо. Я попробую это. – glglgl

+0

Стоит отметить, что на Cortex-R существуют различные различные регистры PSR в зависимости от того, в каком режиме вы находитесь. Вам нужно убедиться, что вы используете правильный! См. Технические справочные руководства Cortex-R, –

+0

@RealtimeRik Разное? Конечно, APSR является псевдонимом для «частей CPSR, доступных из пользовательского режима», но он по-прежнему является тем же самым регистром. Вы не думаете о M-профиле, вы (у которого есть 3 отдельных PSR, плюс псевдонимы для всех возможных комбинаций из них)? – Notlikethat

0

Вы можете использовать _disable_interrupt _(); _ enable_interrupt_(); от генерируемого Halcogen кода (sys_core.h)

+1

Спасибо за ваш ответ. В общем, вы правы, но что, если прерывания были уже отключены по какой-либо причине? Тогда я бы включил их в конце, когда это может быть не то, что действительно нужно. Таким образом, сохранение CPSR и восстановление соответствующих частей, как [предлагается Notlikethat] (http://stackoverflow.com/a/40021747/296974), кажется, имеет решающее значение. – glglgl

+0

Я отправляю только одну строку. В реальном я делаю подсчет уровня гнездования. Кроме того, если вы находитесь внутри прерывания, вам не нужно отключать прерывания. – vromanov

+0

Это зависит от того, знаю ли я, что я внутри прерывания. Предположим, что у меня есть что-то вроде рамки очереди или что-то еще, и мне нужно убедиться, что изменения происходят атомарно. Затем мне нужно безоговорочно отключить прерывания в начале и восстановить ситуацию, как это было раньше, потому что функция библиотеки не знает, вызвана ли она прерыванием или нет. – glglgl

Смежные вопросы