Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32f4 прерывания
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
BlackOps
два вопроса:

1) как лучше объявлять глобальную переменную вне функции main() если я хочу чтобы эта переменная нормально модифицировалась/читалась прерыванием и основной программой?


2) Я заметил проблемы с прерыванием по EXTI, а именно, когда в обработчике прерывания по EXTI я хочу включить прерывание EXTI другого пина, то у меня все вылетает с ошибкой Segmentation Fault, в чем причина этого?

И как правильнее организовать включение одного прерывания (в данном случае EXTI) внутри другого?

Я например делаю так:

первое прерывание ЕХТИ:
Код
// Enable SYSCFG clock
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;


[code]// External interrupt from pin PE2 (EXT1_IN1)
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI2_PE; //

EXTI->IMR |= (1 << 2); // Mask PE2
EXTI->RTSR |= (1 << 2); // Rising Edge detection

NVIC_SetPriority(EXTI2_IRQn, 0x1);

NVIC_EnableIRQ(EXTI2_IRQn);



А вот так выглядит обработчик этого прерывания где включается второе аналогичное:

Код
void EXTI2_IRQHandler()
{

// check if interrupt bit set
if ( (EXTI->PR) & (1 << 2) )
{
    // clear interrupt bit
    EXTI->PR = (1 << 2);

// External interrupt from pin PE4 (EXT1_IN3)
SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI4_PE; //

EXTI->IMR |= (1 << 4); // Mask PE4
EXTI->RTSR |= (1 << 4); // Rising Edge detection

NVIC_SetPriority(EXTI4_IRQn, 0x3);

NVIC_EnableIRQ(EXTI4_IRQn);

}
}


не кладите мой код в codebox, это КОРОТКИЙ код!
andrewlekar
Цитата
1) как лучше объявлять глобальную переменную вне функции main() если я хочу чтобы эта переменная нормально модифицировалась/читалась прерыванием и основной программой?

unsigned char volatile my_var;

Если переменная не атомарная (больше байта длиной) и может модифицироваться и в прерывании, и в main, то нужно окружить обращения к переменной запретом/разрешением прерываний, либо защитить семафорами/мютексами, либо применить иной способ защиты переменной от конкурентного обращения.
shmur
Цитата(andrewlekar @ Jul 31 2013, 09:00) *
либо защитить семафорами/мютексами


Дедлок же будет wacko.gif
Axel
Цитата(BlackOps @ Jul 30 2013, 19:13) *
1) как лучше объявлять глобальную переменную вне функции main() если я хочу чтобы эта переменная нормально модифицировалась/читалась прерыванием и основной программой?


Я объявляю обычным образом или volatile (по необходимости). но для модификации использую циклы ldrex / strex вместо присваивания (ессно без запрета прерываний).
_Артём_
Цитата(andrewlekar @ Jul 31 2013, 08:00) *
Если переменная не атомарная (больше байта длиной)

Почему байта? Для Cortex-M - 4 байта (разрядность регистров CPU).
BlackOps
а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте)
Сергей Борщ
QUOTE (BlackOps @ Aug 1 2013, 11:44) *
а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте)
Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно.
BlackOps
Цитата(Сергей Борщ @ Aug 1 2013, 16:08) *
Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно.

можно узнать какой именно компилятор используете Вы?
Я например отсюда последнюю версию беру: https://launchpad.net/gcc-arm-embedded

А ошибка выдавалась во время отладки с gdb
Сергей Борщ
QUOTE (BlackOps @ Aug 1 2013, 23:41) *
можно узнать какой именно компилятор используете Вы?

CODE
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.7.3 20130312 (release) [ARM/embedded-4_7-branch revision 196615]

QUOTE (BlackOps @ Aug 1 2013, 23:41) *
Я например отсюда последнюю версию беру: https://launchpad.net/gcc-arm-embedded
Аналогично.
QUOTE (BlackOps @ Aug 1 2013, 23:41) *
А ошибка выдавалась во время отладки с gdb
Какой программой выдавалась ошибка? gdb? gdb-сервером? Оболочкой, в которой вы отлаживаетесь?
BlackOps
я пока временно переделал алгоритм, и включаю прерывание в основной программе, так все работает. просто плату рабочую надо было быстро отправить.

как только вторую соберу, повторю ошибку скопирую сюда все данные.
BlackOps
короче я переделал код потом. Одна из задач такая: Активируется внешние прерывание ЕХТI2, внутри него в зависимости от некоторых условий должно быть включено прерывание на ЕХТI4.
т.е. как только программа начинается включено прерывание ЕХТI2 на высокий уровень внешнего сигнала а прерывание ЕХТI4 выключено. Прерывание ЕХТI4 должно включится внутри прерывания ЕХТI2 при соблюдении определенных условий.

разумеется я в начале включаю SYSCFG clock, затем включаю прерывание ЕХТI2.

вот код включения прерывания ЕХТI4 (код включения ЕХТI2 аналогичный только с другой маской):
Код
// External interrupt from pin PE4 (EXT1_IN3)
SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI4_PE; //

EXTI->IMR |= (1 << 4); // Mask PE4
EXTI->RTSR |= (1 << 4); // Rising Edge detection

NVIC_SetPriority(EXTI4_IRQn, 0x3);

NVIC_EnableIRQ(EXTI4_IRQn);

Так вот проблема сейчас в том, что после включения прерывания ЕХТI4, и подачи сигнала 1 на соответствующий пин прерывание ЕХТI4 не срабатывает.
Оно просто не включается и все.

Я уладил это тем что создал глобальную переменную, и вместо того чтобы включать прерывание ЕХТI4 внутри ЕХТI2 я просто меняю значение созданной глобальной переменной, затем из ЕХТI2 программа возвращается к основному циклу, а там происходит проверка глобальной переменной, если ее значение изменено, то внутри основного цикла программы я включаю прерывание ЕХТI4 точно тем куском кода приведенным выше.

И тогда все работает, т.е. подается сигнал уровня 1 на соответствующий пин и все срабатывает как надо.

Стоит мне перенести этот код внутри прерывания ЕХТI2 и опять ничего не работает.
Ошибок дебаггер сейчас не выдает.

В чем же может быть проблема в данном случае? (точно не в железе, т.к. разница между работающим и не работающем прерывании ЕХТI4 только в перестановке вышеуказанного кода между циклом основной программы и телом прерывания ЕХТI2)
Я помню пробовал раньше из одного прерывания включать другое и работало, так выходит иногда это не работает? Но от чего зависит?

Я также пробовал проверить регистры IMR,RTSR просто чтоб убедится что они выставлены как надо когда тот код в теле прерывания ЕХТI2, и все было правильно. Но прерывание просто не активно! т.е. не срабатывает на внешний сигнал.
Axel
У меня похожая ситуация: внутри вектора таймера разрешается внешнее прерывание. Отличия: вся инициализация выполняется в теле основной программы, а в вектор (таймера) включен только короткий фрагмент:
Код
    EXTI->PR = (1 << 1);            // clear ext. int. flag
    __ISB();
    __DSB();
    EXTI->IMR |= (1 << 1);          // enable  rising edge int.

Срeда - CrossWorks. Пока работает...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.