BlackOps 0 30 июля, 2013 Опубликовано 30 июля, 2013 · Жалоба два вопроса: 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 0 31 июля, 2013 Опубликовано 31 июля, 2013 · Жалоба 1) как лучше объявлять глобальную переменную вне функции main() если я хочу чтобы эта переменная нормально модифицировалась/читалась прерыванием и основной программой? unsigned char volatile my_var; Если переменная не атомарная (больше байта длиной) и может модифицироваться и в прерывании, и в main, то нужно окружить обращения к переменной запретом/разрешением прерываний, либо защитить семафорами/мютексами, либо применить иной способ защиты переменной от конкурентного обращения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
shmur 0 31 июля, 2013 Опубликовано 31 июля, 2013 · Жалоба либо защитить семафорами/мютексами Дедлок же будет Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axel 1 31 июля, 2013 Опубликовано 31 июля, 2013 · Жалоба 1) как лучше объявлять глобальную переменную вне функции main() если я хочу чтобы эта переменная нормально модифицировалась/читалась прерыванием и основной программой? Я объявляю обычным образом или volatile (по необходимости). но для модификации использую циклы ldrex / strex вместо присваивания (ессно без запрета прерываний). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 31 июля, 2013 Опубликовано 31 июля, 2013 · Жалоба Если переменная не атомарная (больше байта длиной) Почему байта? Для Cortex-M - 4 байта (разрядность регистров CPU). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BlackOps 0 1 августа, 2013 Опубликовано 1 августа, 2013 · Жалоба а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 1 августа, 2013 Опубликовано 1 августа, 2013 · Жалоба а есть идеи почему когда в одном прерывании включаю другое то выдается Segmentation FAult ошибка? (как описано в первом посте)Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BlackOps 0 1 августа, 2013 Опубликовано 1 августа, 2013 · Жалоба Формулировка "все вылетает" из первого сообщения подразумевает только один ответ - "хз". Кем ошибка выдается? В упор не вижу такого исключения в ядре Cortex-M4. Если это сообщение компилятора - то пишите баг-репорт и ждите более свежей версии, а пока можете пытаться слегка изменить алгоритм - может помочь. Или, если компилятор гнутый, то можете попытаться найти в нем ошибку самостоятельно. можно узнать какой именно компилятор используете Вы? Я например отсюда последнюю версию беру: https://launchpad.net/gcc-arm-embedded А ошибка выдавалась во время отладки с gdb Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 2 августа, 2013 Опубликовано 2 августа, 2013 · Жалоба можно узнать какой именно компилятор используете Вы? $ 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-сервером? Оболочкой, в которой вы отлаживаетесь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BlackOps 0 4 августа, 2013 Опубликовано 4 августа, 2013 · Жалоба я пока временно переделал алгоритм, и включаю прерывание в основной программе, так все работает. просто плату рабочую надо было быстро отправить. как только вторую соберу, повторю ошибку скопирую сюда все данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BlackOps 0 2 сентября, 2013 Опубликовано 2 сентября, 2013 · Жалоба короче я переделал код потом. Одна из задач такая: Активируется внешние прерывание ЕХТ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 1 3 сентября, 2013 Опубликовано 3 сентября, 2013 · Жалоба У меня похожая ситуация: внутри вектора таймера разрешается внешнее прерывание. Отличия: вся инициализация выполняется в теле основной программы, а в вектор (таймера) включен только короткий фрагмент: EXTI->PR = (1 << 1); // clear ext. int. flag __ISB(); __DSB(); EXTI->IMR |= (1 << 1); // enable rising edge int. Срeда - CrossWorks. Пока работает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться