Добрый день.
В программе используются прерывания, прерывание может прервать другое прерывание =)
Основная проблема - malloc() , случается иногда что попадает именно в момент выделения памяти, но и в другом прерывании так же есть выделение памяти. И когда случаются совпадения, то бывает коллапс.
Так вот, что бы не проставлять кучу __disable_irq(); __enable_irq();
как можно некоторые функции целиком защитить от прерывания (но что бы оно было вызвано после выполнения самой функции)? Под целиком я подразумеваю не писать внутри функции команды, а как-то снаружи что ли...
С учётом того, что оборачивать сам вызов функции не вариант (костыль).
Использование __disable_irq(); и __enable_irq(); то же может быть проблемным, т.к. если в вызывающей эту функцию прерывания уже отключены мы можем случайно их включить, чего очень не хочется.
P.S. выделение памяти в прерываниях зло и т.д. ага.
P.P.S. можно настроить, что бы прерывания одно другое не прерывали, но это не подходит, т.к. нужно только некоторые функции, которые вызываются в прерывании.
Для таких целей вводятся дополнительные обертки над disable_irq и enable_irq, которые вычисляют "глубину" запрета прерываний. По факту просто есть глобальный счетчик, который увеличивается при каждом вызове ext_disable_irq и уменьшается при ext_enable_irq. Настоящее включение прерываний происходит в самом конце ext_enable_irq и только если счетчик в этот момент равен нулю
Думал, может есть какой хак...
Тогда придётся все функции переделывать, если в них больше одного ретурна, что бы не забыть включить прерывания обратно...
Kalombyr, обычно функциями отключения и включения прерываний выделяется лишь небольшой участок кода. Рассматривайте это как фигурные скобки, окаймляющие критическую секцию. Если у вас прерывания только выключаются - возможно стоит задуматься над рефакторингом.
15432, насколько плохо вообще то, что использую __disable_irq(); и enable_irq(); ну то есть это ведь не означает, что код полностью говно как только появляется такая необходимость?
Над рефакторингом подумаю...
Kalombyr, если вы абсолютно уверены, что случайно не включите прерывания, когда не надо - всё ок. Зависит от разработанной архитектуры. Большинство решений, с которыми я сталкивался, использовали ту или иную обёртку, чтобы учитывать предыдущее состояние прерываний.
Он вызывает функцию, когда переменная выходит из области видимости (этакий RAII в C). Оберните ваш ext_enable_irq в макрос, который выховет её и создаст переменную, у которой cleanup - ext_disable_irq, и в результате ваши функции будут выглядеть как-то так:
void* func(size_t size)
{
IRQ_GUARD;
//Код собственно функции
}
P.S. выделение памяти в прерываниях зло и т.д. ага.
Дело говоришь. Вообще какая-либо существенная работа в обработчике прерывания -- зло. Избегай этого по возможности.
Так вот, что бы не проставлять кучу __disable_irq(); __enable_irq();
А никак иначе. Но обычно есть возможность делать не disable/enable а save+disable/restore, т.е. запрещать прерывания, одновременно возвращая текущее состояние запрета и восстанавливать это состояние.
Но это нужно =( пробовал уйти, всё равно не к этим так к подобным проблемам пришёл. Скорость работы устраивает.
"а save+disable/restore, т.е. запрещать прерывания, одновременно возвращая текущее состояние запрета и восстанавливать это состояние." можно попросить об этом подробнее рассказать, как именно? (операционка не используются)
Если это нужно, значит плохо спроектировано приложение. По возможности избегай и этого тоже.
"а save+disable/restore, т.е. запрещать прерывания, одновременно возвращая текущее состояние запрета и восстанавливать это состояние." можно попросить об этом подробнее рассказать, как именно?
Судя по тегу STM это ARM? Я не особый любитель ARM, но вот реализации save+disable и restore из linux:
Kalombyr, а это чуть другой подход к обёртке функций disable_irq и enable_irq, который также много где применяется. здесь функция ext_disable_irq возвращает предыдущее состояние прерываний (выключено или включено), а ext_enable_irq наоборот, принимает это значение и включает прерывания только если они ранее были включены. Применяется, если прерываний несколько и настройки выставляются битовыми флагами.
jcmvbkbc, да я про сам подход. если прерываний куча, то полюбому будет сохранение старого состояния. а иначе можно обойтись счетчиком, как я приводил.
вашего примера на момент написания коммента не видел *я буду обновлять страницу*
Покури доку на компилятор который используешь. Во многие компиляторы встроены специальные механизмы, которые можно использовать для запретов и разрешений прерываний. Например есть макросы, которые запрещают прерывания при входе в какой-то блок, а потом либо их разрешают не смотря ни на что либо восстанавливают то значение которое было до входа в этот блок, т.к. если прерывания были запрещены, то они и остаются запрещены.