Перейти к содержанию
    

stm32f4 прерывания

два вопроса:

 

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, это КОРОТКИЙ код!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

unsigned char volatile my_var;

 

Если переменная не атомарная (больше байта длиной) и может модифицироваться и в прерывании, и в main, то нужно окружить обращения к переменной запретом/разрешением прерываний, либо защитить семафорами/мютексами, либо применить иной способ защиты переменной от конкурентного обращения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Я объявляю обычным образом или volatile (по необходимости). но для модификации использую циклы ldrex / strex вместо присваивания (ессно без запрета прерываний).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если переменная не атомарная (больше байта длиной)

Почему байта? Для Cortex-M - 4 байта (разрядность регистров CPU).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте)
Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно.

можно узнать какой именно компилятор используете Вы?

Я например отсюда последнюю версию беру: https://launchpad.net/gcc-arm-embedded

 

А ошибка выдавалась во время отладки с gdb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно узнать какой именно компилятор используете Вы?

$ 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]

Я например отсюда последнюю версию беру: https://launchpad.net/gcc-arm-embedded
Аналогично.

А ошибка выдавалась во время отладки с gdb
Какой программой выдавалась ошибка? gdb? gdb-сервером? Оболочкой, в которой вы отлаживаетесь?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я пока временно переделал алгоритм, и включаю прерывание в основной программе, так все работает. просто плату рабочую надо было быстро отправить.

 

как только вторую соберу, повторю ошибку скопирую сюда все данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

короче я переделал код потом. Одна из задач такая: Активируется внешние прерывание ЕХТ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, и все было правильно. Но прерывание просто не активно! т.е. не срабатывает на внешний сигнал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня похожая ситуация: внутри вектора таймера разрешается внешнее прерывание. Отличия: вся инициализация выполняется в теле основной программы, а в вектор (таймера) включен только короткий фрагмент:

    EXTI->PR = (1 << 1);            // clear ext. int. flag
    __ISB();
    __DSB();
    EXTI->IMR |= (1 << 1);          // enable  rising edge int.

Срeда - CrossWorks. Пока работает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...