реклама на сайте
подробности

 
 
> Запрещение и разрешение прерываний
Tarbal
сообщение Jan 25 2016, 02:55
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Я сгенерировал кубом код для STM32F429 и добавляю в него необходимые мне функции.

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

Вот так определены функции управления запрещением прерывания.
Код
/** \brief  Enable IRQ Interrupts

  This function enables IRQ interrupts by clearing the I-bit in the CPSR.
  Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
  __ASM volatile ("cpsie i" : : : "memory");
}


/** \brief  Disable IRQ Interrupts

  This function disables IRQ interrupts by setting the I-bit in the CPSR.
  Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
  __ASM volatile ("cpsid i" : : : "memory");
}


В дисассемблерном коде я не вижу ничего похожего на них.
Или я чего-то не разглядел?
Посмотрите пожалуйста свежим взглядом.

Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
smalcom
сообщение Jan 25 2016, 18:04
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 292
Регистрация: 26-06-07
Пользователь №: 28 718



Цитата
__disable_irq()

оно?
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Jan 25 2016, 21:22
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



Цитата(smalcom @ Jan 25 2016, 21:04) *
__disable_irq()
оно?

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

Нужно, чтобы одна ассемблерная команда одновременно и записала CPSR в стек и установила в нем запрет прерывания. И обратная операция - восстановиление CPSR из стека без всяких промежуточных операций в регистрах.

Иными словами нужна атомарная операция сохранения старого CPSR в стек с одновременной записью указанного бита в CPSR. Ну и обратная операция - восстановление CPSR из стека.

Честно сказать, совершенно не понимаю, как всякие функции HAL работают без этого - они обязательно должны глючить. Там все время пользуют общее разрешение и запрет прерываний. Если при этом нет возможности честно (атомарно, чтобы никто не мог перебить) сохранить исходное состояние бита разрешения прерываний, то это полный песец.

Цитата(Tarbal @ Jan 25 2016, 22:01) *

Именно так я и делаю, но это не снимает проблемы прерывания между считыванием CPSR и запретом прерываний.

Для кортекса определены странные макро типа CFI_ARM_BLOCK_start и CFI_ARM_BLOCK_end, но что это и как этим пользоваться не нашел.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jan 26 2016, 05:37
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(rudy_b @ Jan 26 2016, 00:22) *
Нет, не оно. Эта функция сначала считывает CPSR в регистр, меняет биты в регистре, потом заносит регистр в CPSR. Если в это время произойдет прерываие и CPSR будет изменен - будет плохо.

Нужно, чтобы одна ассемблерная команда одновременно и записала CPSR в стек и установила в нем запрет прерывания. И обратная операция - восстановиление CPSR из стека без всяких промежуточных операций в регистрах.

Иными словами нужна атомарная операция сохранения старого CPSR в стек с одновременной записью указанного бита в CPSR. Ну и обратная операция - восстановление CPSR из стека.

Честно сказать, совершенно не понимаю, как всякие функции HAL работают без этого - они обязательно должны глючить. Там все время пользуют общее разрешение и запрет прерываний. Если при этом нет возможности честно (атомарно, чтобы никто не мог перебить) сохранить исходное состояние бита разрешения прерываний, то это полный песец.


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

А если хотите странного, то можно например так

Код
__set_FAULTMASK(1); // не уверен, что она так называется, но какой-то инстринсик для записи в фаултмаск точно есть
prim = __get_PRIMASK();
__disable_irq();
__set_FAULTMASK(0);

some_func();

if (!prim)
  __enable_irq();

Go to the top of the page
 
+Quote Post
rudy_b
сообщение Jan 26 2016, 13:28
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



Цитата(Непомнящий Евгений @ Jan 26 2016, 08:37) *
А если хотите странного, то можно например так
Код
__set_FAULTMASK(1); // не уверен, что она так называется, но какой-то инстринсик для записи в фаултмаск точно есть
prim = __get_PRIMASK();
__disable_irq();

Это уже было. Прерывание между этими двумя командами может изменить CPSR

Цитата(GetSmart @ Jan 26 2016, 09:37) *
Суслика не видно. Опишите по шагам суть возникновения бага в такой последовательности действий. Аналогично багу с глобальным запретом IRQ+FIQ у ARM7.

Долго описывать, эта проблема часто встречается, сталкиваюсь с ней не в первый раз. Особенно актальна при использовании чужих стеков.


Цитата(GetSmart @ Jan 26 2016, 09:37) *
А флаг глобального разрешений/запрета прерываний у кортекса в другом месте.


Код
/** \brief  Disable IRQ Interrupts
  This function disables IRQ interrupts by setting the I-bit in the CPSR.
  Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
  __ASM volatile ("cpsid i" : : : "memory");
}


Но, кажется, я понял как можно сделать правильно - использовать программное прерывание. При этом исходное значение CPSR пишется в стек. Поиграюсь.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jan 26 2016, 13:32
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(rudy_b @ Jan 26 2016, 16:28) *
Это уже было. Прерывание между этими двумя командами может изменить CPSR


Между какими командами? После FAULTMASK=1 прерываний не будет...


Go to the top of the page
 
+Quote Post
rudy_b
сообщение Jan 26 2016, 20:00
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



Цитата(Непомнящий Евгений @ Jan 26 2016, 16:32) *
Между какими командами? После FAULTMASK=1 прерываний не будет...

Зато между
prim = __get_PRIMASK();
и
__disable_irq();
вполне могут быть.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jan 27 2016, 05:02
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(rudy_b @ Jan 26 2016, 23:00) *
Зато между
prim = __get_PRIMASK();
и
__disable_irq();
вполне могут быть.


Откуда они возьмутся, если FAULTMASK=1: Prevents the activation of all exceptions except for NMI?


Цитата(GetSmart @ Jan 27 2016, 00:02) *
Из прерываний/исключений можно выйти с намеренно искажённым PSR. И после выхода там будет не то, что было на точке прерывания предыдущего уровня. Только это не должно влиять на правила осторожности предыдущего уровня.


А зачем так делать? Из прерывания можно к примеру стек расстрелять, тоже беда будет... Что б защититься от всего, надо писать для виртуальной машины sm.gif
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 27 2016, 08:50
Сообщение #9


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Непомнящий Евгений @ Jan 27 2016, 09:02) *
А зачем так делать? Из прерывания можно к примеру стек расстрелять, тоже беда будет...

Если заменить все 8 слов, которые прерывание сохранило аппаратно, и ещё заменить несохранённые регистры, то при выходе можно переключить прерванный тред. Если есть гарантия, что был прерван именно тред. Соответственно PSR на выходе из прерывания будет абсолютно другой.

Что содержится в IPSR (который является частью PSR) в мануалах написано, а на что оно влияет я не увидел. То бишь зачем оно там.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 27 2016, 10:07
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(GetSmart @ Jan 27 2016, 10:50) *
то при выходе можно переключить прерванный тред. Если есть гарантия, что был прерван именно тред. Соответственно PSR на выходе из прерывания будет абсолютно другой.
Но и вернемся мы из такого переключателя в другое место, в то место, где прервали другую нить, а не туда где только что переключалось разрешение прерываний. А вот когда после какого-то следующего переключения вернемся в первое место, в PSR снова будет то же самое содержимое, которое было в момент возникновения прерывания в этом месте.

Цитата(GetSmart @ Jan 26 2016, 02:24) *
Общие функции, вызываемые из прерываний и извне прерываний.
И что? Они точно так же сохранят в себе текущее состояние прерываний и восстановят перед выходом. А иначе ну глупо же получится - работала-работала себе программа, вдруг в производьном ее месте происходит внешнее событие (вызывающее прерывание) и после его обработки дальше программа вдруг дальше (со случайного места!) работает уже с запрещенными прерываниями. Бред какой-то.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 27 2016, 13:00
Сообщение #11


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Сергей Борщ @ Jan 27 2016, 14:07) *
Бред какой-то.

О переключении треда - это на совсем другой вопрос мой ответ был. А общие функции - это общие функции с некими критическими секциями, как хотел автор топика. Просто он что-то сформулировать не может.

Сообщение отредактировал GetSmart - Jan 27 2016, 13:01


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Tarbal   Запрещение и разрешение прерываний   Jan 25 2016, 02:55
- - SII   Похоже, в дизассемблере команды разрешения-запреще...   Jan 25 2016, 04:41
- - johnshadow   Регулярно наблюдаю такие приколы у кокосовского де...   Jan 25 2016, 07:32
- - Tarbal   Спасибо за ответы. Картинку я залил воспользовав...   Jan 25 2016, 11:47
|- - Сергей Борщ   Отожмите иконку "Show Source" на рамке о...   Jan 25 2016, 12:19
- - rudy_b   Кстати, еще вопрос по той же теме. Нужна функция з...   Jan 25 2016, 15:25
|- - Tarbal   Цитата(rudy_b @ Jan 25 2016, 19:25) Кстат...   Jan 25 2016, 19:01
|- - GetSmart   Цитата(rudy_b @ Jan 25 2016, 19:25) Пробл...   Jan 26 2016, 00:24
|- - rudy_b   Цитата(GetSmart @ Jan 26 2016, 03:24) Как...   Jan 26 2016, 03:42
|- - GetSmart   Цитата(rudy_b @ Jan 26 2016, 07:42) В дан...   Jan 26 2016, 06:37
|- - Сергей Борщ   Цитата(rudy_b @ Jan 25 2016, 23:22) Честн...   Jan 25 2016, 23:11
||- - Tarbal   Цитата(Сергей Борщ @ Jan 26 2016, 02:11) ...   Jan 27 2016, 14:20
||- - Сергей Борщ   Цитата(Tarbal @ Jan 27 2016, 16:20) Разре...   Jan 27 2016, 22:08
||- - Tarbal   Цитата(Сергей Борщ @ Jan 28 2016, 01:08) ...   Jan 28 2016, 12:15
||- - Сергей Борщ   Цитата(Tarbal @ Jan 28 2016, 14:15) Но по...   Jan 28 2016, 12:43
|- - GetSmart   Цитата(rudy_b @ Jan 26 2016, 17:28) Кодpr...   Jan 26 2016, 21:02
- - rudy_b   Мы говорим о разных вещах. Попробую более узко сфо...   Jan 27 2016, 14:11
|- - GetSmart   Цитата(rudy_b @ Jan 27 2016, 18:11) Но фу...   Jan 27 2016, 22:52
- - AVI-crak   Цитата(Tarbal @ Jan 25 2016, 09:55) Я сге...   Jan 27 2016, 18:59
- - rudy_b   Все совершенно справедливо. Но переписывать стек н...   Jan 28 2016, 04:00
|- - GetSmart   Цитата(rudy_b @ Jan 28 2016, 08:00) Да и ...   Jan 28 2016, 04:51
- - GetSmart   У NXP ARM7 была такая особенность ARM spurious IRQ...   Jan 29 2016, 02:01


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 09:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01488 секунд с 7
ELECTRONIX ©2004-2016