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

 
 
> повторные прерывания LPC17xx
evgen2
сообщение Jan 14 2014, 23:32
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 236
Регистрация: 1-04-06
Пользователь №: 15 688



Вот похожая тема В прерываниях CM0/CM3 в конце нужен ClearPending?

Имеем такой простой до невозможности код
Код
/* таймер T2  25 МГц */
   LPC_TIM2->MR0 = 782/2;           // 782 = 32 кHz
   LPC_TIM2->MCR = 3;                
   LPC_TIM2->TCR=  0x01;
   NVIC_EnableIRQ(TIMER2_IRQn);

void TIMER2_IRQHandler(void)
{    static int raz=0;
     if(raz == 0)
     {  LPC_GPIO2->FIOSET = 0x1000;raz = 1;
     } else {
       LPC_GPIO2->FIOCLR = 0x1000; raz = 0;
   }
    LPC_TIM2->IR = 1; // Clear interrupt flag
}


смотрим осциилографом, что получается:

___|___|___|___

Или наоборот

— — |— — |— — |— —

Вместо ожидаемого — — |___|— — |___|— — |___

При этом, если поставить брякпойнт на FIOSET или FIOCLR, а потом убрать и продолжить, то картина меняется
если мерять время этого второго паразита, то это будет 12-14 клоков
Однако, если перенести IR = 1; в начало
Код
void TIMER2_IRQHandler(void)
{    static int raz=0;
      LPC_TIM2->IR = 1; // Clear interrupt flag
     if(raz == 0)
     {  LPC_GPIO2->FIOSET = 0x1000;raz = 1;
     } else {
       LPC_GPIO2->FIOCLR = 0x1000; raz = 0;
   }
}


То все налаживается....

Теперь смотрю на все остальные прервывания, в том числе GPI прерывания GPIO прерывания Rising/Falling edge приходят одновременно? (2 ноги * прерывания по фронту и спаду) - там тоже получается какое-то левое повторное прерывание.. однако манипуляции с выносом очистки прерывания как можно раньше не прокатывают и, кажется, наоборот, от выноса очистки в конец количество левых прерываний уменьшается

ЗЫ: а в эмуляторе это не вылазит

Сообщение отредактировал evgen2 - Jan 15 2014, 00:07
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 22)
_Артём_
сообщение Jan 14 2014, 23:50
Сообщение #2


Гуру
******

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



Цитата(evgen2 @ Jan 15 2014, 01:32) *

Если память не изменяет - не нужен, но вот где это написано не помню (изменяет таки) а искать лень.

Цитата(evgen2 @ Jan 15 2014, 01:32) *
То все налаживается....
Может что такое добавить, хотя у вас не RTC...


Код
OS_INTERRUPT void OS::SystemTimer_ISR()
{
    /* Clear interrupt source */
    RTC->IFC=RTC_IFC_COMP0;
    /* Flushing instructions to make sure that the interrupt is not re-triggered*/
    /* This may be required when the peripheral clock is slower than the core */
    __DSB();
    {
    scmRTOS_ISRW_TYPE ISR;

#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
        system_timer_user_hook();
#endif
        Kernel.system_timer();
    }

}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 15 2014, 07:54
Сообщение #3


Гуру
******

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



Цитата(evgen2 @ Jan 15 2014, 01:32) *
То все налаживается....
Угу. Это влияние конвеера. Или сбрасывайте в начале, или вставляйте барьер синхронизации после сброса флага.


--------------------
На любой вопрос даю любой ответ
"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
evgen2
сообщение Jan 15 2014, 09:41
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 236
Регистрация: 1-04-06
Пользователь №: 15 688



Цитата(Сергей Борщ @ Jan 15 2014, 11:54) *
Угу. Это влияние конвеера. Или сбрасывайте в начале, или вставляйте барьер синхронизации после сброса флага.


"Барьер синхронизации" - это "заклинание" __DSB(); ? Непонятно, почему ни в мануалах, ни в примерах его нет
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 15 2014, 09:50
Сообщение #5


Гуру
******

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



Цитата(evgen2 @ Jan 15 2014, 11:41) *
"Барьер синхронизации" - это "заклинание" __DSB(); ?
Ну хотя бы по диагонали просмотрите начало документа по ссылке.
Цитата(evgen2 @ Jan 15 2014, 11:41) *
Непонятно, почему ни в мануалах, ни в примерах его нет
Я вам дал ссылку как раз на мануал с примером.


--------------------
На любой вопрос даю любой ответ
"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
evgen2
сообщение Jan 15 2014, 18:33
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 236
Регистрация: 1-04-06
Пользователь №: 15 688



Цитата(Сергей Борщ @ Jan 15 2014, 13:50) *
Ну хотя бы по диагонали просмотрите начало документа по ссылке.
Я вам дал ссылку как раз на мануал с примером.

да хоть по диагонали, хоть на принтере распечатать да на просвет посмотреть . Может оно и влияет, если засыпать-просыпаться, а без этого - никакой разницы
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Jan 15 2014, 22:32
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118






Due to the processor pipeline, the Cortex-M processors can be entering the interrupt sequence
at the same time as writing to the NVIC to disable the interrupt. Therefore, it is possible that an
interrupt handler might be executed immediately after it is disabled at the NVIC.

http://infocenter.arm.com/help//topic/com....r_m_profile.pdf


--------------------
ASB
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2014, 06:48
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Aleksandr Baranov @ Jan 16 2014, 04:32) *
Due to the processor pipeline, the Cortex-M processors can be entering the interrupt sequence
at the same time as writing to the NVIC to disable the interrupt. Therefore, it is possible that an
interrupt handler might be executed immediately after it is disabled at the NVIC.

Мимо кассы. Так как у ТС нет запретов прерываний внутри ISR, и даже вообще обращений к NVIC внутри ISR.
Go to the top of the page
 
+Quote Post
swisst
сообщение Jan 16 2014, 09:55
Сообщение #9


Частый гость
**

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



Доброго дня ! на контроллере 1768 с MC0 и таймером проблем не имею.
Код
void TIMER0_IRQHandler(){
    uint32_t _interrupt_source = LPC_TIM0->IR;

    if(_interrupt_source & (1<<0)){
        LPC_TIM0->IR |= (1<<0);
                //дальше код - барьеров нет
    }
}


я бы для чистоты эксперимента объявил бы еще переменную как volatile
Код
static int raz=0;

или вовсе бы ушел от нее
Код
LPC_GPIO2->FIOPIN ^= 0x1000;
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2014, 10:48
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



1. Вот потому, что "дальше код", потому и не имеете rolleyes.gif
2. Операция if(_interrupt_source & (1<<0)){ бессмысленна, так как если у вас установлены ещё и другие флаги запросов в IF, то функция всё равно зациклится в непрерывных входах в ISR (ведь регистра маски прерываний в таймере вроде нету?).
3. Операция |= в LPC_TIM0->IR |= (1<<0); также бессмысленна, читайте UM.
4. volatile объявлять бессмысленно если переменная больше нигде не используется (а она больше нигде не используется).
5. Делать так: LPC_GPIO2->FIOPIN ^= 0x1000; крайне опасно, если учесть, что в основном коде (или другом ISR) могут быть операции с другими битами этого порта. Курите UM на предмет - зачем придуманы FIOSET и FIOCLR.

PS: И вообще - лучше молчать, чем давать такие "советы".
Лучше поучитесь хотя-бы у ТС как правильно реализовывать ISR-ы.
Go to the top of the page
 
+Quote Post
swisst
сообщение Jan 16 2014, 12:30
Сообщение #11


Частый гость
**

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



Цитата(jcxz @ Jan 16 2014, 12:48) *
1. Вот потому, что "дальше код", потому и не имеете rolleyes.gif


частота дерганья ножкой 40kHz. обработчик упростил
Код
void TIMER0_IRQHandler(){
    if(LPC_TIM0->IR & (1<<0)){

        LED3_TOG;      //LPC_GPIO2->FIOPIN ^= 0x1000;

    }

    LPC_TIM0->IR = (1<<0);
}

все работает, как и раньше. в UM ни слова о том, в каком месте сбрасывать флаг.


Цитата(jcxz @ Jan 16 2014, 12:48) *
2. Операция if(_interrupt_source & (1<<0)){ бессмысленна, так как если у вас установлены ещё и другие флаги запросов в IF, то функция всё равно зациклится в непрерывных входах в ISR (ведь регистра маски прерываний в таймере вроде нету?).
3. Операция |= в LPC_TIM0->IR |= (1<<0); также бессмысленна, читайте UM.

это не принципиально в конкретном примере. прерывания по MATCH и CAP маскируются.

Цитата(jcxz @ Jan 16 2014, 12:48) *
4. volatile объявлять бессмысленно если переменная больше нигде не используется (а она больше нигде не используется).
5. Делать так: LPC_GPIO2->FIOPIN ^= 0x1000; крайне опасно, если учесть, что в основном коде (или другом ISR) могут быть операции с другими битами этого порта. Курите UM на предмет - зачем придуманы FIOSET и FIOCLR.

я же написал - для чистоты эксперимента. иначе получается, что вы знаете о том, что переменная нигде не используется, но не знаете, что порт 2 пустой rolleyes.gif
Go to the top of the page
 
+Quote Post
sidy
сообщение Jan 16 2014, 16:13
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Допустим, у меня есть следующий обработчик прерываний:
Код
void TIM1_TRG_COM_TIM11_IRQHandler(void){
  if(TIM11->SR&TIM_SR_UIF){
      TIM11->SR&=~TIM_SR_UIF;
      __disable_irq();
      TIM4->CNT=(TIM11->CNT*5.25f/168.0f)
      TIM4->CR1|=TIM_CR1_CEN;              
      __enable_irq();                      
  }
}

нужно ли мне ставить после __enable_irq(); __ISB()?

Сообщение отредактировал sidy - Jan 16 2014, 16:14
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2014, 16:54
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(sidy @ Jan 16 2014, 22:13) *
нужно ли мне ставить после __enable_irq(); __ISB()?

Скажем по-другому: вам скорее всего не нужно ставить __disable_irq()/__enable_irq().
Зачем они? У вас что - в другом, более приоритетном ISR осуществляется запись в эти регистры??? smile3046.gif

Цитата(swisst @ Jan 16 2014, 18:30) *
я же написал - для чистоты эксперимента. иначе получается, что вы знаете о том, что переменная нигде не используется, но не знаете, что порт 2 пустой rolleyes.gif

Что переменная нигде не используется я знаю из static int, а то что порт больше нигде - об этом ни слова.
К тому же переменных типа int в ОЗУ можно создать ГОРАЗДО больше чем обычно имеется портов в МК. Если вы так расточительно будете подходить к ногам, что на одну ногу будете тратить целый 32-битный порт, то далеко не уедете...
Go to the top of the page
 
+Quote Post
sidy
сообщение Jan 16 2014, 17:18
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(jcxz @ Jan 16 2014, 20:54) *
Скажем по-другому: вам скорее всего не нужно ставить __disable_irq()/__enable_irq().
Зачем они? У вас что - в другом, более приоритетном ISR осуществляется запись в эти регистры???

Например, если между записью в регистр CNT и пуском таймера TIM_CR1_CEN придет более приоритетное прерывание, то TIM11->CNT может сделать n-ое количество тактов и значение TIM4->CNT будет некорректным.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2014, 18:24
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Как же можно ответить ответить на Ваш вопрос, если невозможно догадаться, что у вас за регистры такие SR и CNT?
В UM на LPC17xx таковых нету.
Ну если под CNT ещё можно предположить регистр TC, то с SR вообще теряюсь в догадках....
Подозреваю что у вас не LPC17x. А в таком случае нужно указывать какой CPU имеете в виду если вопрос касается периферии и желательно указывать как она у вас сконфигурена.
Go to the top of the page
 
+Quote Post
sidy
сообщение Jan 16 2014, 18:57
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(jcxz @ Jan 16 2014, 22:24) *
Как же можно ответить ответить на Ваш вопрос, если невозможно догадаться, что у вас за регистры такие SR и CNT?
В UM на LPC17xx таковых нету.
Ну если под CNT ещё можно предположить регистр TC, то с SR вообще теряюсь в догадках....
Подозреваю что у вас не LPC17x. А в таком случае нужно указывать какой CPU имеете в виду если вопрос касается периферии и желательно указывать как она у вас сконфигурена.

Да у меня STM32F407, но думаю что переферия таймеров очень похожа с LPC17x отличия только а названиях регистров.
TIM11->CNT - счетный регистр таймера
TIM11->SR - регистр статуса таймера
TIM_SR_UIF - флаг в регистре статуса, который устанавливается при прерывании

Сообщение отредактировал sidy - Jan 16 2014, 19:09
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2014, 19:39
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Только в LPC флаги прерываний квтируются не записью '0', а записью '1'.
Отвечая на Ваш вопрос, думаю что вряд-ли будет проблема из-за отсутствия барьеров после квитирования флага прерывания, так как после этой операции и до выхода из ISR у вас много команд, так что сброс флага должен успеть дойти до периферии таймера до выхода из ISR.
И опять-же - что за мания такая использовать операции чтения-модификации-записи там где нужна просто запись? А остальные флаги потерять не боитесь? Да и просто - ЗАЧЕМ????
Go to the top of the page
 
+Quote Post
sidy
сообщение Jan 16 2014, 19:44
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(jcxz @ Jan 16 2014, 23:39) *
И опять-же - что за мания такая использовать операции чтения-модификации-записи там где нужна просто запись? А остальные флаги потерять не боитесь? Да и просто - ЗАЧЕМ????

Немного не понял где у меня чтение-модификация-запись и как сделать просто запись? И какие флаги можно потерять?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 17 2014, 07:06
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



это стандартная ошибка при сбросах флагов

REG |= INTERRUPT_FLAG;

обычно эти регистры не чувствительны к одному сигналу и реагируют только на другой. в LPC, например запись 0 ничего не делает, а запись 1 сбрасывает флаг. Если в регистре лежит
0x11, а мы хотим сбросить FLAG = 0x01.
то запись REG |= FLAG равносильна REG = REG | FLAG => REG = 0x11 | 0x01 => REG = 0x11 => REG ==== 0;
то есть сбрасывая один флаг, мы случайно сбросили все остальные что были в регистрах...

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

REG = FLAG => REG = 0x01 => REG ==== 0x10; То есть запись 0 в старшие биты, где стоит флаг его не тронет, снимется только младший флаг.
Go to the top of the page
 
+Quote Post
sidy
сообщение Jan 17 2014, 07:33
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Понял, т.е. мы прочитали, изменили, записали в регистр число 0x11 и сбросили 0-й бит и 5ый бит.
Т.е. операция вида REG&=~FLAG тоже относится к чтения модификация запись:
REG&=~FLAG => REG=REG&(~FLAG) => REG=0x11&(~0x10) => REG=0x11&(0x01) => REG=0x01?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 17 2014, 10:18
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



скорее так
REG&=~FLAG => REG=REG&(~FLAG) => REG=0x11&(~0x01) => REG=0x11&(0x10) => REG=0x10?
FLAG = 01
и при сбросе 0 все вроде сработает, но есть и вторая опасность.

REG = 0x011
операция
REG&=~FLAG
не делается за 1 такт

вы получите значение регистра 0x011
на след шаге 0x011 & 0x110 = 0x010 (FLAG = 0x001, ~FLAG = 0x110)
и в конце получите
REG = 0x010
младший флаг сбрасываете, второй не трогаете (это все про сброс нулем)

но если за время этих трех тактов произошло прерывание
и регистр стал REG = 0x111,
то появившийся самый старший бит вы тоже сбросите.

а если вы сразу напишите
REG = (~FLAG)

то все будет хорошо даже если произойдет прерывание во время выполнения команды сброса.


Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 17 2014, 10:50
Сообщение #22


Гуру
******

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



Цитата(sidy @ Jan 17 2014, 09:33) *
Т.е. операция вида REG&=~FLAG тоже относится к чтения модификация запись:
Ага, только REG=0x11&(~0x10) => REG=0x11&(0xEF) => REG=0x10, то есть сбросили все флаги кроме нужного


--------------------
На любой вопрос даю любой ответ
"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
Golikov A.
сообщение Jan 17 2014, 20:17
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата(Сергей Борщ @ Jan 17 2014, 14:50) *
Ага, только REG=0x11&(~0x10) => REG=0x11&(0xEF) => REG=0x10, то есть сбросили все флаги кроме нужного


не это мы типа говорим про процы со сбросом 0, а не 1. Но смысл один, сбрасывать используя состояние регистра - нельзя!
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 04:30
Рейтинг@Mail.ru


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