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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Запрещение и разрешение прерываний
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
SII
сообщение Jan 25 2016, 04:41
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414



Похоже, в дизассемблере команды разрешения-запрещения прерываний просто не отобразились. Вызов функции report втоит у Вас по адресу 1818A. Поскольку команда BL занимает 4 байта, следующая команда должна быть по адресу 1818E, а у Вас сразу идёт 18190 -- т.е. пропущены два байта, а CPS как раз двухбайтовая. Т.е. мне кажется, что это дизассемблер дурной.

Пы.Сы. А хостинг для картинки Вы неудачный выбрали: щёлкаешь на неё, чтобы посмотреть в полном размере, а вместо картинки тебе предлагают залить своё и всё такое.
Go to the top of the page
 
+Quote Post
johnshadow
сообщение Jan 25 2016, 07:32
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 31
Регистрация: 25-09-08
Пользователь №: 40 477



Регулярно наблюдаю такие приколы у кокосовского дебаггера (там вроде GDB).
Добавьте в "after build"
Код
"${gcc.home}/arm-none-eabi-objdump -d -S ${project.bin}/${output.name}.elf > ${project.bin}/${output.name}.lst"

получите .lst и в нем посмотрите

Сообщение отредактировал johnshadow - Jan 25 2016, 07:32
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Jan 25 2016, 11:47
Сообщение #4


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

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



Спасибо за ответы.

Картинку я залил воспользовавшись кнопкой в диалоге для сообщения в форуме. Не делал этого раньше. Наверное чтоьто сделал не так.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 25 2016, 12:19
Сообщение #5


Гуру
******

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



Отожмите иконку "Show Source" на рамке окна дизассемблера. Пропавшие команды появятся. Правда исчезнут вкрапления исходного текста в дизассемблер.
Цитата(Tarbal @ Jan 25 2016, 13:47) *
Картинку я залил воспользовавшись кнопкой в диалоге для сообщения в форуме. Не делал этого раньше. Наверное чтоьто сделал не так.
Не, это у нас движок на форуме такой. В следующий раз нажимайте "расширенная форма" и там будет возможность прикрепить файл прямо в сообщение, без внешних файлохранилищ. После выбора и загрузки файла появится возможность вставить его в нужное место сообщения, разберетесь.


--------------------
На любой вопрос даю любой ответ
"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
rudy_b
сообщение Jan 25 2016, 15:25
Сообщение #6


Знающий
****

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



Кстати, еще вопрос по той же теме. Нужна функция запрета прерываний, которая при последующем разрешении прерываний сможет точно восстановить предыдущее состояние разрешения прерываний ( I-bit CPSR) для кортекса М3 (stm32f207).

Проблема в том, что если я ручками задвину регистр CPSR в стек и, затем, запрещу прерывания, то при возникновении прерывания между этими двумя командами (а оно может изменить параметры прерываний), я получу не то состояние и не смогу восстановить реальное исходное состояние параметров прерываний.

Может есть команда, которая сразу и запомнит текущее состояние разрешения прерываний в стеке и запретит их? Ну, хотя бы, сохранит регистр CPSR или только его I-bit?
Go to the top of the page
 
+Quote Post
smalcom
сообщение Jan 25 2016, 18:04
Сообщение #7


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

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



Цитата
__disable_irq()

оно?
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Jan 25 2016, 19:01
Сообщение #8


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

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



Цитата(rudy_b @ Jan 25 2016, 19:25) *
Кстати, еще вопрос по той же теме. Нужна функция запрета прерываний, которая при последующем разрешении прерываний сможет точно восстановить предыдущее состояние разрешения прерываний ( I-bit CPSR) для кортекса М3 (stm32f207).

Проблема в том, что если я ручками задвину регистр CPSR в стек и, затем, запрещу прерывания, то при возникновении прерывания между этими двумя командами (а оно может изменить параметры прерываний), я получу не то состояние и не смогу восстановить реальное исходное состояние параметров прерываний.

Может есть команда, которая сразу и запомнит текущее состояние разрешения прерываний в стеке и запретит их? Ну, хотя бы, сохранит регистр CPSR или только его I-bit?


http://stm32f4-discovery.com/2015/06/how-t...n-arm-cortex-m/


Цитата(Сергей Борщ @ Jan 25 2016, 16:19) *
Отожмите иконку "Show Source" на рамке окна дизассемблера. Пропавшие команды появятся. Правда исчезнут вкрапления исходного текста в дизассемблер.
Не, это у нас движок на форуме такой. В следующий раз нажимайте "расширенная форма" и там будет возможность прикрепить файл прямо в сообщение, без внешних файлохранилищ. После выбора и загрузки файла появится возможность вставить его в нужное место сообщения, разберетесь.


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


Знающий
****

Группа: Свой
Сообщений: 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 25 2016, 23:11
Сообщение #10


Гуру
******

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



Цитата(rudy_b @ Jan 25 2016, 23:22) *
Честно сказать, совершенно не понимаю, как всякие функции HAL работают без этого - они обязательно должны глючить.
Может потому, что они не пытаются разрешать/запрещать прерывания из обработчиков этих самых прерываний? Интересно, зачем такое может понадобиться?


--------------------
На любой вопрос даю любой ответ
"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 26 2016, 00:24
Сообщение #11


.
******

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



Цитата(rudy_b @ Jan 25 2016, 19:25) *
Проблема в том, что если я ручками задвину регистр CPSR в стек и, затем, запрещу прерывания, то при возникновении прерывания между этими двумя командами (а оно может изменить параметры прерываний), я получу не то состояние и не смогу восстановить реальное исходное состояние параметров прерываний.

Какие параметры? Какое состояние?


Цитата(Сергей Борщ @ Jan 26 2016, 03:11) *
Интересно, зачем такое может понадобиться?

Общие функции, вызываемые из прерываний и извне прерываний.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Jan 26 2016, 03:42
Сообщение #12


Знающий
****

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



Цитата(GetSmart @ Jan 26 2016, 03:24) *
Какие параметры? Какое состояние?

В данный момент - состояние бита разрешения прерываний в CPSR.

Ну а если это получится сделать корректно, то все остальное - дело техники.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jan 26 2016, 05:37
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 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
GetSmart
сообщение Jan 26 2016, 06:37
Сообщение #14


.
******

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



Цитата(rudy_b @ Jan 26 2016, 07:42) *
В данный момент - состояние бита разрешения прерываний в CPSR.

Суслика не видно. Опишите по шагам суть возникновения бага в такой последовательности действий. Аналогично багу с глобальным запретом IRQ+FIQ у ARM7. А флаг глобального разрешений/запрета прерываний у кортекса в другом месте.

Сообщение отредактировал GetSmart - Jan 26 2016, 06:52


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Jan 26 2016, 13:28
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 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

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

 


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


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