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

 
 
> Работа с прерываниями в at91sam7s, не вызывается повторное прерывание
Bulat
сообщение Jul 7 2009, 03:57
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Конфигурация прерываний происходит следующим образом:
Код
void RT()
{
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_PIOA, 0x06, AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, irq_RT);
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW2_MASK);
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW3_MASK); //Маска прерываний на PA23, PA24
//* set the interrupt by software
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);
  while(1); //Ожидание прерывания
}


Обработчик прерываний:
Код
__ramfunc void irq_RT()
{  
  //Определение источника прерывания и запрет прерываний
  int i_status = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);
  if(i_status&0x800000) AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA,SW3_MASK);   //Прерывание пришло от PA23
  if(i_status&0x1000000) AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA,SW2_MASK);   //Прерывание пришло от PA24
  AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);
  ...
  //программа обработки прерывания
  ...
  //Разрешение прерываний
  if(i_status&0x800000) AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW3_MASK);
  if(i_status&0x1000000) AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW2_MASK);
  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);


Первое прерывание нормально обрабатывается, но второе прерывание не обрабатывается, хотя источником является тот же вывод (PA24). Чтобы обработать следующее прерывание, приходится презагружать устройство и заново вызывать прерывание. То есть больше одного прерывания подряд не обрабатывает. Почемутак происходит, я ведь правильно конфигурирую прерывания?
Заранее благодарен!
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 32)
SergeiCh
сообщение Jul 7 2009, 04:37
Сообщение #2


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

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Тему не в том разделе создали, надо в помощь начинающим.

Излишеств много. Запрещать прерывания не надо. Вы пока это не обработаете, вторично в него не попадете - приоритет один. Убедитесь, что возвращаетесь в RT(). И не меняется ли у Вас i_status.

Код
void RT(void)
{
    AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_PIOA, 0x06, AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, irq_RT);
    AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, SW2_MASK | SW3_MASK); //Маска прерываний на PA23, PA24
    //* set the interrupt by software
    AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);
    while(1); //Ожидание прерывания
}

__ramfunc void irq_RT(void)
{  
  //Определение источника прерывания
  int i_status = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);
   ...
  //программа обработки прерывания
  ...
}
Go to the top of the page
 
+Quote Post
dimka76
сообщение Jul 7 2009, 08:35
Сообщение #3


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Цитата(Bulat @ Jul 7 2009, 07:57) *
Первое прерывание нормально обрабатывается, но второе прерывание не обрабатывается, хотя источником является тот же вывод (PA24).

Перед выходом из обработчика прерывания надо произвести запись в регистр AIC_EOICR любого значения.

Цитата
The End of Interrupt Command Register is used by the interrupt routine to indicate treatment is complete.


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
Troll
сообщение Jul 7 2009, 09:07
Сообщение #4


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Цитата(dimka76 @ Jul 7 2009, 14:35) *
Перед выходом из обработчика прерывания надо произвести запись в регистр AIC_EOICR любого значения.
Ага, и еще надо восстанавливать PC = LR - 4 и CPSR. Обычно и то и другое делается в общем irq-обработчике из startup.S.

Цитата
Убедитесь, что возвращаетесь в RT().
И также, проверьте, что точно второй раз не вызывается функция irq_RT().


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 7 2009, 11:32
Сообщение #5


Гуру
******

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



Ну, добавим еще традиционную и очевидную ошибку - AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE.
Вот почему всем неймется настроить прерывания от внутренних некомбинированных источников на работу по фронту?

Если писать без маразмов, то получится как-то так:
Код
void RT(void)
{
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)irq_RT;
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 6;
    AT91C_BASE_AIC->AIC_IECR = (1UL << AT91C_ID_PIOA);
    AT91C_BASE_SYS->PIOA_IER = SW2_MASK | SW3_MASK;
}

__irq void irq_RT(void)
{
    unsigned int status = AT91C_BASE_SYS->PIOA_ISR;
    if(status & SW2_MASK)
    {
        ...
    }
    if(status & SW3_MASK)
    {
        ...
    }
    AT91C_BASE_AIC->AIC_EOICR = status;
}
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Jul 7 2009, 12:49
Сообщение #6


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

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(aaarrr @ Jul 7 2009, 18:32) *
Если писать без маразмов,
Код
    AT91C_BASE_AIC->AIC_EOICR = status;

Как заметил Troll, в стандартном startup.s это уже есть.
INT_POSITIVE_EDGE недосмотрел sad.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 7 2009, 12:53
Сообщение #7


Гуру
******

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



Цитата(SergeiCh @ Jul 7 2009, 16:49) *
Как заметил Troll, в стандартном startup.s это уже есть.

Ну я же написал "без маразмов". "Стандартный" (и кто же его стандартизировал-то?) стартап к таковым относится.
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Jul 7 2009, 15:43
Сообщение #8


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

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Цитата(aaarrr @ Jul 7 2009, 19:53) *
(и кто же его стандартизировал-то?)

Хорошо, данный нам в softpack Atmel и растиражированный IAR. wink.gif

BTW, если его не подправить, Ваш пример с __irq работать не будет. В тамошнем startup, насколько помню, lr корректируется (sub lr, lr, #4), примерно то же делает директива __irq, т.е. от lr будет дважды отниматься 4. С другой стороны, если в таблице векторов уже ldr pc, [pc,#-0xF20], как в startup "по умолчанию" у Keil, без __irq оно могло залетать в какой-нибудь abort. Надо смотреть, что в startup у топикстартера.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 7 2009, 15:49
Сообщение #9


Гуру
******

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



Цитата(SergeiCh @ Jul 7 2009, 19:43) *
Надо смотреть, что в startup у топикстартера.

Да, надо. Причем топикстартеру, а не нам.

Хорошо бы как объявление закрепить:
Цитата
Внимание!

При создании темы типа "прерывание на ARM не работает" прикладывайте стартап или область векторов, не заставляйте окружающих прибегать к телепатии.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jul 8 2009, 08:47
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Jul 7 2009, 21:49) *
Да, надо. Причем топикстартеру, а не нам.

Хорошо бы как объявление закрепить:

Спасибо за ответы.
Прикрепляю стартап, изменил расширение, так как s79 не дает загрузить.
Прикрепленные файлы
Прикрепленный файл  Cstartup.txt ( 10.21 килобайт ) Кол-во скачиваний: 122
 
Go to the top of the page
 
+Quote Post
Troll
сообщение Jul 8 2009, 09:34
Сообщение #11


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Не сильно хорошо разбираюсь в Ассемблере. Но на первый взгляд ничего "противозаконного" не заметил.
Проверьте после выхода из прерывания, программа возвращается в основной цикл или нет?

Хотя, на счет "все нормально" я поспешил.
Команда "В" изменяет регистр LR (адрес текущей команды) и после выполнения команд:
Код
            sub         lr, lr, #4
            stmfd       sp!, {lr}
будет сохранен отнюдь не адрес команды на которой произошло прерывание.
Вместо команды "В" используйте команду "LDR".

Сообщение отредактировал Troll - Jul 8 2009, 09:54


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jul 8 2009, 09:48
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(Troll @ Jul 8 2009, 15:34) *
Не сильно хорошо разбираюсь в Ассемблере. Но на первый взгляд ничего "противозаконного" не заметил.
Проверьте после выхода из прерывания, программа возвращается в основной цикл или нет?

В основном цикле включается светодиод, подключенный к РА0
Код
void RT(void)
{
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)irq_RT;
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 6;
    AT91C_BASE_AIC->AIC_IECR = (1UL << AT91C_ID_PIOA);
    AT91C_BASE_SYS->PIOA_IER = SW2_MASK | SW3_MASK;
    
    while(1) { regs->PIOA_ODSR = 0x0080001; }
}

Так вот, после обработки прерывания светодиод загорается, если нет дерективы __irq перед обработчиком. Если стоит деректива, то светодиод не загорается, стало быть из прерывания не возвращается.
Но, даже когда загорается диод, то есть программа возвращается в основной цикл, повторно перейти к обработчику она не может, хотя прерывание вызывается также, как и в первом случае.
Go to the top of the page
 
+Quote Post
Troll
сообщение Jul 8 2009, 10:49
Сообщение #13


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Цитата(Bulat @ Jul 8 2009, 15:48) *
Так вот, после обработки прерывания светодиод загорается, если нет дерективы __irq перед обработчиком. Если стоит деректива, то светодиод не загорается, стало быть из прерывания не возвращается.

не знаю каким компилятором Вы пользуетесь, но в общем случае директива __irq вставляет в код функции строки:
Код
            sub         lr, lr, #4
            stmfd       sp!, {lr} //Список может быть и больше
... //тело фукнции
            ldmia       sp!, {pc}^

Поэтому с Вашим обработчиком и директивой IRQ из прерывания программа будет улетать в ближний космос. Об этом чуть выше уже писал SergeiCh.


Вопрос, а с чего Вы взяли, что светодиод загорается после выхода из обработчика?
Код
while(1) { regs->PIOA_ODSR = 0x0080001; }
этот код вообще не показатель.


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 8 2009, 11:47
Сообщение #14


Гуру
******

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



Цитата(Troll @ Jul 8 2009, 13:34) *
Команда "В" изменяет регистр LR (адрес текущей команды)

Команда B не изменяет LR, изменяет BL.

Цитата(Bulat @ Jul 8 2009, 13:48) *
Так вот, после обработки прерывания светодиод загорается, если нет дерективы __irq перед обработчиком.

С таким стартапом __irq не нужен.

Но я бы рекомендовал выкинуть IRQ_Handler_Entry, а вместо
Код
                B           IRQ_Handler_Entry  ; 0x18 IRQ

поставить
Код
    ldr        pc, [pc, #-0xf20]    ; IRQ

И вернуть __irq обработчикам.

Цитата(Bulat @ Jul 8 2009, 13:48) *
Но, даже когда загорается диод, то есть программа возвращается в основной цикл, повторно перейти к обработчику она не может, хотя прерывание вызывается также, как и в первом случае.

Выложите полностью основную программу и обработчик в текущем состоянии. А то совершенно непонятно, как получаются такие выводы.
Go to the top of the page
 
+Quote Post
Troll
сообщение Jul 8 2009, 11:59
Сообщение #15


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Цитата(aaarrr @ Jul 8 2009, 17:47) *
Но я бы рекомендовал выкинуть IRQ_Handler_Entry, а вместо
Код
                B           IRQ_Handler_Entry ; 0x18 IRQ

поставить
Код
    ldr        pc, [pc, #-0xf20]; IRQ

И вернуть __irq обработчикам.

aaarrr а с чем связана такая рекомендация? Как это работает я понимаю, но мне интересна Ваша точка зрения, чем один вариант лучше другого.


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 8 2009, 12:13
Сообщение #16


Гуру
******

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



Цитата(Troll @ Jul 8 2009, 15:59) *
aaarrr а с чем связана такая рекомендация? Как это работает я понимаю, но мне интересна Ваша точка зрения, чем один вариант лучше другого.

Связана с явной глупостью "стандартного" стартапа - все прерывания обрабатываются как вложенные с соответствующим оверхедом.
При прямом переходе по вектору из AIC мы получаем возможность использовать обычные обработчики прерываний с модификатором __irq, а в случае использования вложенных прерываний - не сохранять контекст для прерываний с наивысшим приоритетом и сэкономить ручное чтение IVR (при некотором оверхеде по объему, но лишняя сотня байт на обработчик по современным понятиям не считается).
Go to the top of the page
 
+Quote Post
Troll
сообщение Jul 8 2009, 12:46
Сообщение #17


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Цитата(aaarrr @ Jul 8 2009, 18:13) *
а в случае использования вложенных прерываний - не сохранять контекст для прерываний с наивысшим приоритетом и сэкономить ручное чтение IVR.

Что-то я не понял, что Вы сказали.
Вложенное прерывание, по моему представлению, это когда выполняется обработка одного прерывания и произошло прерывание с более высоким приоритетом и происходит вызов обработчика этого нового прерывания. Контекст - LR и другие РОН.

Что в этом случае значит "не сохранять контекст для прерываний с наивысшим приоритетом и сэкономить ручное чтение IVR"?


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 8 2009, 12:51
Сообщение #18


Гуру
******

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



Цитата(Troll @ Jul 8 2009, 16:46) *
Что в этом случае значит "не сохранять контекст для прерываний с наивысшим приоритетом и сэкономить ручное чтение IVR"?

Я не совсем понятно выразился, похоже. Не сохранять контекст - значит не пихать LR_irq и SPSR_irq на стек и не переключать режим процессора для прерываний с высшим приоритетом.
Ручное чтение IVR исключается для всех прерываний.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jul 9 2009, 10:38
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Jul 8 2009, 17:47) *
Команда B не изменяет LR, изменяет BL.


С таким стартапом __irq не нужен.

Но я бы рекомендовал выкинуть IRQ_Handler_Entry, а вместо
Код
                B           IRQ_Handler_Entry ; 0x18 IRQ

поставить
Код
    ldr        pc, [pc, #-0xf20]; IRQ

И вернуть __irq обработчикам.


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

Спасибо! Прерывания нормально работают. Тут у меня новая неполадка выявилась)
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jul 9 2009, 23:26
Сообщение #20


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(aaarrr @ Jul 8 2009, 16:13) *
Связана с явной глупостью "стандартного" стартапа - все прерывания обрабатываются как вложенные с соответствующим оверхедом.
При прямом переходе по вектору из AIC мы получаем возможность использовать обычные обработчики прерываний с модификатором __irq, а в случае использования вложенных прерываний - не сохранять контекст для прерываний с наивысшим приоритетом и сэкономить ручное чтение IVR (при некотором оверхеде по объему, но лишняя сотня байт на обработчик по современным понятиям не считается).
+1000
Я в паре топиков говорил про вредность "общих" обработчиков допускающих вложенные прерывания,
но понимания не достиг..., наверное у Вас лучше получиться объяснить.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Aug 5 2009, 05:37
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Прерывание вызывается по внешнему сигналу от порта. В качестве сигнала вызова подпрограммы обработки прерывания у меня моргает светодиод 2 раза. Точнее, должен моргать. На самом деле, светодиод моргает 4 раза, то есть обработчик вызывается 2 раза. При этом осциллограф показал всего один импульс на входе внешнего прерывания. Я ввел в обработчик функции, запрещающие прерывания, но это не помогло.
Код
//Инициализация прерывания
__ramfunc void RT()
{
    //Настройка портов ввода-ввывода
    regs->PIOA_OER = 0x22490000;      
    regs->PIOA_ODR = ~0x22490000;
    
    regPIO->PIO_PPUDR = 0x63DDFFFF;  
    regs->PIOA_OWER = 0x2249ffff;
    regs->PIOA_OWDR = ~0x2249ffff;          
    regs->PIOA_ODSR = 0x0080000; //R/W=0, REG=0, STRB=1
      
    // Load System pAic Base address
        
    AT91F_AIC_ConfigureIt_MY( AT91C_BASE_AIC, AT91C_ID_PIOA, 0x06, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, irq_RT);
    AT91F_PIO_InterruptEnable_MY(AT91C_BASE_PIOA,SW2_MASK);
    AT91F_PIO_InterruptEnable_MY(AT91C_BASE_PIOA,SW3_MASK);
    // set the interrupt by software
    AT91F_AIC_EnableIt_MY(AT91C_BASE_AIC, AT91C_ID_PIOA);  
                                                    
    while(1){regs->PIOA_ODSR = 0x0080000;}                                    //Ожидание прерывания
    
    
}//RT()

//Обработчик прерываний
__ramfunc void irq_RT()
{    
  int i_status = 0x0;
  i_status = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);
  if(i_status&0x800000) AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA,SW3_MASK);   //Прерывание пришло от PA23
  if(i_status&0x1000000) AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA,SW2_MASK);   //Прерывание пришло от PA24
  AT91F_AIC_DisableIt_MY(AT91C_BASE_AIC, AT91C_ID_PIOA);
  
  //Прием командного слова
  if(i_status&0x800000) regs->PIOA_ODSR = 0x400000;                             //REG=0, R/W=1, STRB=0, CHA/CHB=0 ïðè CHA
  if(i_status&0x1000000) regs->PIOA_ODSR = 0x410000;                            //REG=0, R/W=1, STRB=0, CHA/CHB=1 ïðè CHB    
  PIO_copy = regs->PIOA_PDSR;                                                   //считываем данные с порта контроллера
  regs->PIOA_ODSR = 0x0080000;
  if(PIO_copy != 0x0) i_PIO=1;
  
   if(i_PIO == 1)
  {
    i = 300000;
      while(i!=0)
      {
        if(i>=200000 & i<=300000) regs->PIOA_ODSR = 0x0080001; //Лампочка горит
        if(i>=100000 & i<200000) regs->PIOA_ODSR = 0x0080000;  //не горит
        if(i<100000) regs->PIOA_ODSR = 0x0080001;                     //горит
        i--;
      }
    i_PIO=0;  
  }

AT91C_BASE_AIC->AIC_EOICR = status;                                          
  if(i_status&0x800000) AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW3_MASK);
  if(i_status&0x1000000) AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW2_MASK);
  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PIOA);    
}


Почему прерывание 2 раза вызывается, если внешний сигнал только один?
Заранее благодарен. файл стартапа прилагается
Прикрепленные файлы
Прикрепленный файл  Cstartup.txt ( 10.21 килобайт ) Кол-во скачиваний: 19
 
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Aug 5 2009, 05:46
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(Bulat @ Aug 5 2009, 08:37) *
if(i>=200000 & i<=300000) regs->PIOA_ODSR = 0x0080001; //Лампочка горит
if(i>=100000 & i<200000) regs->PIOA_ODSR = 0x0080000; //не горит


Должно быть:

Код
        if(i>=200000 && i<=300000) regs->PIOA_ODSR = 0x0080001; //Лампочка горит
        if(i>=100000 && i<200000) regs->PIOA_ODSR = 0x0080000;  //не горит
Go to the top of the page
 
+Quote Post
Troll
сообщение Aug 5 2009, 06:20
Сообщение #23


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Отключать прерывания не нужно.
Код
AT91F_AIC_DisableIt_MY(AT91C_BASE_AIC, AT91C_ID_PIOA);
После того как вновь включаете, должна быть команда очистки прерываний (не помню точно как регистр называется).

Цитата(sergeeff @ Aug 5 2009, 09:46) *
Должно быть:

Код
        if(i>=200000 && i<=300000) regs->PIOA_ODSR = 0x0080001; //Лампочка горит
        if(i>=100000 && i<200000) regs->PIOA_ODSR = 0x0080000;  //не горит

вот так, помоему даже красивше:
Код
        if((200000<=i) && (i<=300000)) regs->PIOA_ODSR = 0x0080001; //Лампочка горит

Код
AT91C_BASE_AIC->AIC_EOICR = status;
А вот этого уже не нужно. В стартапе уже есть
Код
;- Mark the End of Interrupt on the AIC
            ldr         r14, =AT91C_BASE_AIC
            str         r14, [r14, #AIC_EOICR]


Код
if(i_status&[b]0x800000[/b]) AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA,[b]SW3_MASK[/b]);   //Прерывание пришло от PA23
Почему бы просто не написать i_status&SW3_MASK

И код
Код
  PIO_copy = regs->PIOA_PDSR;                                                   //считываем данные с порта контроллера
  if(PIO_copy != 0x0) i_PIO=1;
  
   if(i_PIO == 1)
Можно заменить просто одним условным оператором.

Сообщение отредактировал Troll - Aug 5 2009, 06:21


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
Bulat
сообщение Aug 5 2009, 07:25
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



спасибо за ответы, но это не решает основной проблемы. Лампочка мигает 4 раза вместо 2-х, то есть прерывание дважды вызывается, хотя я вызываю его один раз.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Aug 5 2009, 07:55
Сообщение #25


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



В конце обработчика прерывания сбросьте флаг перывания

Код
volatile int dummy = AT91C_BASE_PIOA->PIO_ISR;
Go to the top of the page
 
+Quote Post
Bulat
сообщение Aug 5 2009, 09:39
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(sergeeff @ Aug 5 2009, 13:55) *
В конце обработчика прерывания сбросьте флаг перывания

Код
volatile int dummy = AT91C_BASE_PIOA->PIO_ISR;

Спасибо, заработало)
Go to the top of the page
 
+Quote Post
Troll
сообщение Aug 5 2009, 10:48
Сообщение #27


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

Группа: Участник
Сообщений: 104
Регистрация: 30-06-05
Из: С-Петербург
Пользователь №: 6 406



Цитата(sergeeff @ Aug 5 2009, 11:55) *
В конце обработчика прерывания сбросьте флаг перывания

Код
volatile int dummy = AT91C_BASE_PIOA->PIO_ISR;

А я решил, что PIO_ISR читается здесь
Код
i_status = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);


--------------------
Hemos Pasado
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 5 2009, 11:52
Сообщение #28


Гуру
******

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



Цитата(Troll @ Aug 5 2009, 14:48) *
А я решил, что PIO_ISR читается здесь

Привильно решили. Прерывание генерируется по любому изменению уровня PIO, поэтому один импульс вызовет два прерывания.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 5 2009, 12:08
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sergeeff @ Aug 5 2009, 10:55) *
Код
volatile int dummy = AT91C_BASE_PIOA->PIO_ISR;

"Труды" Редькина плодоносят, блин sad.gif
Зачем здесь
Код
volatile int dummy =

sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Aug 5 2009, 12:36
Сообщение #30


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Уважаемый Гуру!

Я прекрасно помню про вашу нелюбовь к подобным
Код
volatile int dummy
. Ваши идеи на сей счет прекрасно работают в С, но не везде в С++ (именно в нем я работаю). Посему мой совет - это copy/past из живого кода.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 5 2009, 14:14
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sergeeff @ Aug 5 2009, 15:36) *
Ваши идеи...

Это не идеи и тем более не мои. Это совершенно естественное поведение компилятора не имеющего никакого права игнорировать обращение к volatile переменной.
Цитата
на сей счет прекрасно работают в С, но не везде в С++ (именно в нем я работаю).

Вам только осталось найти в стандарте на C++ отличия от C в поведении volatile переменых, позволяющие распоряжаться C++ компиляторам volatile по своему усмотрению.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Aug 5 2009, 16:35
Сообщение #32


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Вы же сами признавались в топике (http://electronix.ru/forum/index.php?showtopic=54275&st=15), что
Цитата
Ну что я могу сказать - много значит cтранностей в IARовском недоплюсовом компиляторе. Подчеркиваю еще раз ПЛЮСОВОМ, а тема начинслась как C/C99.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Aug 5 2009, 20:09
Сообщение #33


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(sergeeff @ Aug 5 2009, 11:55) *
В конце обработчика прерывания сбросьте флаг перывания

Код
volatile int dummy = AT91C_BASE_PIOA->PIO_ISR;

Не смотря на различия С и плюсов,
у Вас здесь явно лишним будет volatile перед int dummy,
PIO_ISR уже объявлен как volatile для чтения,
поэтому гарантировать запись этого(не нужного) значения куда-то
нет никакого смысла...
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 01:59
Рейтинг@Mail.ru


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