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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Вложенные прерываня
Andrew2000
сообщение Jul 10 2006, 15:53
Сообщение #31


Местный
***

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



Цитата(aaarrr @ Jul 8 2006, 18:12) *
Цитата(Andrew2000 @ Jul 8 2006, 17:48) *

Написал такое, но асм для ARM я почти не знаю, может кто подскажет как оптимизировать?

Здесь посмотрите. Пост №48 by sergeeff.

Спасибо, то, что надо.
Go to the top of the page
 
+Quote Post
Nixon
сообщение Jul 10 2006, 16:08
Сообщение #32


Гуру
******

Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48



Цитата(moonrock @ Jul 8 2006, 22:37) *
блин, тут все такие умные, один умней другого, аж страшно задавать следующий глупый вопрос smile.gif , но всё же задам: мой компилятор(keil uVision) не знает ключевое слово __nested, чем вы пользуетесь?

Keil не нужно __nested для описания вложенных прерываний. Достаточно пользоваться макросами IENABLE и IDISABLE в функции обработчика прерывания. Очень хорошие примеры вложенных прерываний (там почти все обработчики сделаны этими макросами с поддержкой вложенных прерываний) есть у филипса в примерах кода к lpc21xx (адрес не знаю, искать "code.bundle.lpc213x.lpc214x.uvision.zip").

В качестве примера
Код
void EINT1_Handler (void) __irq
{
    EXTINT = EINT1;        /* clear interrupt */
        
    IENABLE;            /* handles nested interrupt */
    eint1_counter++;
    if ( eint1_counter & 0x01 )    /* alternate the LED display */
    {
    IOSET1 = 0x000F0000;    /* turn off P1.20~23 */    
    IOCLR1 = 0x00F00000;    /* turn on P1.16~19 */
    }
    else
    {
    IOSET1 = 0x00F00000;    /* turn on P1.20~23 */    
    IOCLR1 = 0x000F0000;    /* turn off P1.16~19 */
    }
    IDISABLE;
    VICVectAddr = 0;        /* Acknowledge Interrupt */
}


Сами макросы тоже просты
Код
// Macros for Interrupt Nesting
#define IENABLE                             /* Nested Interrupts Entry */   \
  __asm { MRS     LR, SPSR      }           /* Copy SPSR_irq to LR     */   \
  __asm { STMFD   SP!, {LR}     }           /* Save SPSR_irq           */   \
  __asm { MSR     CPSR_c, #0x1F }           /* Enable IRQ (Sys Mode)   */   \
  __asm { STMFD   SP!, {LR}     }           /* Save LR                 */   \

#define IDISABLE                            /* Nested Interrupts Exit  */   \
  __asm { LDMFD   SP!, {LR}     }           /* Restore LR              */   \
  __asm { MSR     CPSR_c, #0x92 }           /* Disable IRQ (IRQ Mode)  */   \
  __asm { LDMFD   SP!, {LR}     }           /* Restore SPSR_irq to LR  */   \
  __asm { MSR     SPSR_cxsf, LR }           /* Copy LR to SPSR_irq     */   \


--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2006, 16:25
Сообщение #33


Гуру
******

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



Цитата(Nixon @ Jul 10 2006, 19:08) *
В качестве примера
Код
void EINT1_Handler (void) __irq
{
    EXTINT = EINT1;        /* clear interrupt */
        
    IENABLE;            /* handles nested interrupt */
         ....................
    IDISABLE;
    VICVectAddr = 0;        /* Acknowledge Interrupt */
}
Скорее всего я чего-то не понимаю, но все же: как может вызваться в этом примере вложенное прерывание если VICVectAddr = 0; стоит в самом конце обработчика? Ведь пока не сделан VICVectAddr = 0 контроллер не выдаст адрес следующего обработчика?


--------------------
На любой вопрос даю любой ответ
"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
aaarrr
сообщение Jul 10 2006, 16:34
Сообщение #34


Гуру
******

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



Цитата(Сергей Борщ @ Jul 10 2006, 20:25) *
Скорее всего я чего-то не понимаю, но все же: как может вызваться в этом примере вложенное прерывание если VICVectAddr = 0; стоит в самом конце обработчика? Ведь пока не сделан VICVectAddr = 0 контроллер не выдаст адрес следующего обработчика?

До записи VICVectAddr может быть вызвано только прерывание с более высоким приоритетом.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2006, 17:06
Сообщение #35


Гуру
******

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



Цитата(aaarrr @ Jul 10 2006, 19:34) *
До записи VICVectAddr может быть вызвано только прерывание с более высоким приоритетом.

Проверить достаточно легко, можно и о PrimeCell почитать первоисточник. Но по логике вещей так быть не может, ибо в этом случае при возникновении последовательно прерываний от разных источников будут потеряны все низкоприоритетные, если процесс обработки не успеет считать значение из VicVectAddr и оно будет перезаписано более приоритетным адресом обработчика. В общем как ни крути именно процедура произвольной записи в VicVectAddr логично разрешает занесение нового (вне зависимости от его приоритета) значения в этот регистр. Ну а примеры, как это почти всегда :-( бывает просто фуфло.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 10 2006, 17:12
Сообщение #36


Гуру
******

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



Цитата(zltigo @ Jul 10 2006, 21:06) *
Проверить достаточно легко, можно и о PrimeCell почитать первоисточник.

Вот и почитайте:
Код
Reading from the Vector Interrupt Address Register,
VICVECTADDR, provides the address of the ISR, and updates the interrupt priority
hardware that masks out the current, and any lower priority interrupt requests. Writing
to the VICVECTADDR Register indicates to the interrupt priority hardware that the
current interrupt is serviced, enabling lower priority or the same priority interrupts to be
removed, and for the interrupts to become active to go active.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2006, 17:25
Сообщение #37


Гуру
******

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



Цитата(aaarrr @ Jul 10 2006, 20:12) *
Код
Reading from the Vector Interrupt Address Register,
......

Достаточно убедительно и в такой трактовке работоспособно, хотя настораживает фраза "the same priority", которых быть не должно.
Короче желательно проверить электроникой, что и сделаю сегодня.

Проверено!
Действительно, чтение " Vector Interrupt Address Register" несет дополнительную функциональную нагрузку в виде перетасовки приоритетов и даже без последующей записи
позволяет функционировать более приоритетным прерываниям. Это хорошо, обязательно использую!
Эксперимент проводился на LPC2148 у которого контроллер прерываний от ARM прикручен.

Сообщение отредактировал zltigo - Jul 10 2006, 18:00


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Angle
сообщение Oct 1 2007, 10:55
Сообщение #38


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 8-08-07
Из: Екатеринбург
Пользователь №: 29 638



Подскажите, если кто знает, пример кода для обработчика вложенных прерываний для AT91SAM7A3, компилятор Keil.
Go to the top of the page
 
+Quote Post
xelax
сообщение Oct 2 2007, 05:52
Сообщение #39


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Цитата(Angle @ Oct 1 2007, 14:55) *
Подскажите, если кто знает, пример кода для обработчика вложенных прерываний для AT91SAM7A3, компилятор Keil.


Из примеров на сайте atmela wink.gif Исходя из примера вложенность прерываний делается просто.
В филипсах таким вопросом не озадачивался, поэтому не совсем понятно зачем народ здесь копья ломает 07.gif

Код
irq_handler:
/*- Manage Exception Entry */
/*- Adjust and save LR_irq in IRQ stack */
        sub      lr, lr, #4
        stmfd    sp!, {lr}
/*- Save r0 and SPSR in IRQ stack */
        mrs      r14, SPSR
        stmfd    sp!, {r0,r14}

/*- Write in the IVR to support Protect Mode */
/*- No effect in Normal Mode */
/*- De-assert the NIRQ and clear the source in Protect Mode */
        ldr      r14, =AT91C_BASE_AIC
        ldr      r0 , [r14, #AIC_IVR]
        str      r14, [r14, #AIC_IVR]

/*- Enable Interrupt and Switch in Supervisor Mode */
        msr      CPSR_c, #ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
        stmfd    sp!, {r1-r3, r12, r14}

/*- Branch to the routine pointed by the AIC_IVR */
        mov      r14, pc
        bx       r0

/*- Restore scratch/used registers and LR from User Stack */
        ldmia    sp!, {r1-r3, r12, r14}

/*- Disable Interrupt and switch back in IRQ mode */
        msr      CPSR_c, #ARM_MODE_IRQ | I_BIT

/*- Mark the End of Interrupt on the AIC */
        ldr      r14, =AT91C_BASE_AIC
        str      r14, [r14, #AIC_EOICR]

/*- Restore SPSR_irq and r0 from IRQ stack */
        ldmia    sp!, {r0,r14}
        msr      SPSR_cxsf, r14

/*- Restore adjusted  LR_irq from IRQ stack directly in the PC */
        ldmia    sp!, {pc}^
Go to the top of the page
 
+Quote Post
Tannen
сообщение Jun 18 2009, 13:17
Сообщение #40


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 16-02-08
Пользователь №: 35 104



Мои пять копеек вопроса про вложенные прерывания. на LPC2148 делаю захват CAP0 по таймеру TIMER0.
По отдельности от сигнала подаваемого на все 4 входа захвата( синхронный фронт на все 4 входа) - все работает - счетчик импульсов тикает.
Когда все вместе ( захватывается только 1-он первый канал (((
пишу под IAR. мой код прерываний - т.к. инициализация корректна
Код
__irq __nested __arm void irq_handler (void)
{
void (*interrupt_function)();
  unsigned int vector;
   vector = VICVectAddr;                   // Get interrupt vector.
   interrupt_function = (void(*)())vector; // Call MM_TIMER0_ISR thru pointer
  (*interrupt_function)();  // Call vectored interrupt function
  VICVectAddr = 0;          // Clear interrupt in VIC
}

void  MM_TIMER0_ISR()
{
   volatile unsigned int iPR;
  unsigned char PriA;
if(T0IR_bit.CR0INT)
  {
  
    TVK[0]++;
    if(VKN&0x01)
         {
           TCapi[0]=TCap[0];
           TCap[0] =T0CR0;
         }
    if(TVK[0]==1) VKN&=~0x01;
  T0IR_bit.CR0INT=1; // clear interrupt
  }
  
  // CAP_1
  if(T0IR_bit.CR1INT)
  {
    TVK[1]++;
    if (VKN&0x02)
    {
         TCapi[1]=TCap[1];
         TCap[1] =T0CR1;
    }
    if(TVK[1]==1) VKN&=~0x02;
   T0IR_bit.CR1INT=1;  // clear inteerupt
  }
  if(T0IR_bit.CR2INT)
  {  
     TVK[2]++;
    if (VKN&0x04)
    {
      TCapi[2]=TCap[2];
      TCap[2] =T0CR2;
    }
    if(TVK[2]==1) VKN&=~0x04;
  T0IR_bit.CR2INT=1;
  }
  
  if(T0IR_bit.CR3INT)
  {  
     TVK[3]++;
    if (VKN&0x08)
    {
      TCapi[3]=TCap[3];
      TCap[3] =T0CR3;
    }
    if(TVK[3]==1) VKN&=~0x08;
    T0IR_bit.CR3INT=1;
  }

Ну и как здесь будет реализована вложенность прерываний? ято я не так делаю ? (((
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 18 2009, 14:01
Сообщение #41


Гуру
******

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



Цитата(Tannen @ Jun 18 2009, 16:17) *
Код
  T0IR_bit.CR0INT=1; // clear interrupt

что я не так делаю ? (((
В этой строчке вы сбрасываете не только этот флаг, но и все остальные. Потому что доступ к битовому полю происходит как операция "чтение-модификация-запись" чтобы не испортить остальные поля. Откуда же компилятору знать, что для этого регистра так делать нельзя. Это раз.
Второе - непонятно, зачем вам тут вложенные прерывания. Разрешаются вложенные прерывания только более высокого приоритета, т.е. в этот же обработчик вы не попадете.
Третье - вынесите свой irq_handler в ассемблерный файл в виде команды LDR PC,[PC, #-0x0FF0] прямо на векторе прерывания, а VICVectAddr = 0 и __irq __arm перенесите в каждый обработчик. Вот тут пример для SAM7, для LPC меняются имена регистров. Это позволит компилятору генерить максимально эффективные (короткие) прологи/эпилоги и существенно повысит скорость обработки прерываний, а вам позволит использовать __nested только для тех обработчиков, в которых он действительно нужен (например, в самых приоритетных он не нужен - прервать такой обработчик некому - и только замедляет эти самые важные обработчики).
Четвертое - вам надо в этом обработчике организовать цикл do{}while(T0IR);


--------------------
На любой вопрос даю любой ответ
"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
KeiserSose
сообщение Jun 19 2009, 07:30
Сообщение #42





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



Цитата(GetSmart @ Jul 8 2006, 22:32) *
Повторный вызов не схлопотать. Запрещаются все приоритеты равные и ниже текущего. А то, что нельзя делать одинаковые приоритеты я и сам жалею. Помню как удобно было на 51/52 процах с трёхуровневой системой прерываний. Быстро и удобно.

В данном вопросе только один минус - лишняя многоуровневость. Но гораздо больше плюсов. Особенно быстрое время реакции на все прерывания с учётом приоритетов. А медленные софтверные прерывания вообще не сделать без вложенности.


Не-а. Я бы советовал не использовать обычные прерывания без особой необходимости. Особенно длинные или использующие много стека.


Повторный вызов можно схлопотать элементарно. VicVectAddr=0 открывает ВСЕ прерывания. Нужно явно маскировать и восстанавливать приоритеты.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 19 2009, 07:36
Сообщение #43


Гуру
******

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



Цитата(KeiserSose @ Jun 19 2009, 11:30) *
Повторный вызов можно схлопотать элементарно. VicVectAddr=0 открывает ВСЕ прерывания. Нужно явно маскировать и восстанавливать приоритеты.


Ошибаетесь:
Цитата
Writing to the VICVECTADDR Register indicates to the interrupt priority hardware that the
current interrupt is serviced, enabling lower priority or the same priority interrupts to be
removed, and for the interrupts to become active to go active.
Go to the top of the page
 
+Quote Post
KeiserSose
сообщение Jun 19 2009, 09:11
Сообщение #44





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



Цитата(aaarrr @ Jun 19 2009, 10:36) *
Ошибаетесь:


Если мы обсуждаем версию ARM PrimeCell, используемую в большинстве LPC, то ошибаетесь Вы. Действительно, при чтении VicVectAddr, контроллер повышает приоритет разрешенных прерываний до уровня текущего прерывания. Это обеспечивает правильный вход в стэк прерываний, но только до первой записи в VicVectAddr, что сбрасывает логику контроллера. Таким образом, незавершенные ISR могут прерываться прерываниямм с более низким приоритетом, если прерывания этого типа разрешены в CPSR. Макросы Keil'a просто открывают прерывания. Никакого "Handle nested interrupt" в них нет. VicSWPriorityMask должен быть использован для правильной реализации вложенности.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 19 2009, 10:07
Сообщение #45


Гуру
******

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



Цитата(KeiserSose @ Jun 19 2009, 13:11) *
Если мы обсуждаем версию ARM PrimeCell, используемую в большинстве LPC, то ошибаетесь Вы.

Во-первых, и так понятно, что речь шла о pl190, у pl192 этот регистр называется VICADDRESS.
Во-вторых читаем (pl192):
Цитата
The PrimeCell VIC implements two forms of interrupt priority masking:

Hardware masking
The hardware masking is applied whenever an interrupt is being serviced,
either with a read from the VICADDRESS Register, or by asserting the
VICIRQACK input when the VIC port is used. This prevents other
active interrupts of an equal or lower priority generating a new IRQ while
the interrupt service routine is being executed. When the interrupt routine
has completed and the VICADDRESS Register has been written to, the
interrupt mask is cleared to allow all enabled interrupt sources through.
Note
The VICIRQSTATUS and VICRAWINTR Registers are not affected by
this masking.

Software masking
The software masking is applied using the value programmed into the
VICSWPRIORITYMASK Register. This mask is applied continuously,
and at the same time as the hardware mask when an interrupt is being
serviced.
Note
The values in the VICIRQSTATUS and VICRAWINTR Registers do not
reflect the masking by the VICSWPRIORITYMASK Register.

и еще:
Цитата
Writing to the VICADDRESS
Register indicates to the interrupt priority hardware that the current interrupt is serviced,
enabling the masking of lower priority or the same priority interrupts to be removed and
for the interrupts to become active.

И как получается вывод
Цитата
VicSWPriorityMask должен быть использован для правильной реализации вложенности.

?

Программное управление приоритетами было введено в дополнение к аппаратному, и никак его не отменяет:
Цитата
Software-programmable interrupt priority level masking added, in addition to the
hardware priority level masking.
Go to the top of the page
 
+Quote Post

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

 


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


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