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

 
 
 
Reply to this topicStart new topic
> stm32f4 прерывания, изменение переменных прерыванием, и включение другого прерывания
BlackOps
сообщение Jul 30 2013, 16:13
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121



два вопроса:

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


--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 31 2013, 05:00
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



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

unsigned char volatile my_var;

Если переменная не атомарная (больше байта длиной) и может модифицироваться и в прерывании, и в main, то нужно окружить обращения к переменной запретом/разрешением прерываний, либо защитить семафорами/мютексами, либо применить иной способ защиты переменной от конкурентного обращения.
Go to the top of the page
 
+Quote Post
shmur
сообщение Jul 31 2013, 09:57
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 28-11-11
Пользователь №: 68 553



Цитата(andrewlekar @ Jul 31 2013, 09:00) *
либо защитить семафорами/мютексами


Дедлок же будет wacko.gif
Go to the top of the page
 
+Quote Post
Axel
сообщение Jul 31 2013, 10:56
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



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


Я объявляю обычным образом или volatile (по необходимости). но для модификации использую циклы ldrex / strex вместо присваивания (ессно без запрета прерываний).
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jul 31 2013, 12:45
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(andrewlekar @ Jul 31 2013, 08:00) *
Если переменная не атомарная (больше байта длиной)

Почему байта? Для Cortex-M - 4 байта (разрядность регистров CPU).
Go to the top of the page
 
+Quote Post
BlackOps
сообщение Aug 1 2013, 09:44
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121



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


--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 1 2013, 12:08
Сообщение #7


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"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
BlackOps
сообщение Aug 1 2013, 21:41
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121



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

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

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


--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 2 2013, 09:34
Сообщение #9


Гуру
******

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



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-сервером? Оболочкой, в которой вы отлаживаетесь?


--------------------
На любой вопрос даю любой ответ
"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
BlackOps
сообщение Aug 4 2013, 20:16
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121



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

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


--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
Go to the top of the page
 
+Quote Post
BlackOps
сообщение Sep 2 2013, 23:23
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121



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


--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
Go to the top of the page
 
+Quote Post
Axel
сообщение Sep 3 2013, 03:39
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



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

Срeда - CrossWorks. Пока работает...
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:32
Рейтинг@Mail.ru


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