|
|
  |
Вложенные прерываня |
|
|
|
Jul 10 2006, 15:53
|
Местный
  
Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675

|
Цитата(aaarrr @ Jul 8 2006, 18:12)  Цитата(Andrew2000 @ Jul 8 2006, 17:48)  Написал такое, но асм для ARM я почти не знаю, может кто подскажет как оптимизировать? Здесь посмотрите. Пост №48 by sergeeff. Спасибо, то, что надо.
|
|
|
|
|
Jul 10 2006, 16:08
|
Гуру
     
Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48

|
Цитата(moonrock @ Jul 8 2006, 22:37)  блин, тут все такие умные, один умней другого, аж страшно задавать следующий глупый вопрос  , но всё же задам: мой компилятор(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 */ \
--------------------
Вам помочь или не мешать?
|
|
|
|
|
Jul 10 2006, 16:25
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jul 10 2006, 17:25
|

Гуру
     
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 1 2007, 10:55
|
Участник

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

|
Подскажите, если кто знает, пример кода для обработчика вложенных прерываний для AT91SAM7A3, компилятор Keil.
|
|
|
|
|
Oct 2 2007, 05:52
|

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

|
Цитата(Angle @ Oct 1 2007, 14:55)  Подскажите, если кто знает, пример кода для обработчика вложенных прерываний для AT91SAM7A3, компилятор Keil. Из примеров на сайте atmela  Исходя из примера вложенность прерываний делается просто. В филипсах таким вопросом не озадачивался, поэтому не совсем понятно зачем народ здесь копья ломает Код 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}^
|
|
|
|
|
Jun 18 2009, 13:17
|
Участник

Группа: Участник
Сообщений: 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; } Ну и как здесь будет реализована вложенность прерываний? ято я не так делаю ? (((
|
|
|
|
|
Jun 18 2009, 14:01
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jun 19 2009, 07:30
|
Группа: Новичок
Сообщений: 4
Регистрация: 17-11-08
Пользователь №: 41 713

|
Цитата(GetSmart @ Jul 8 2006, 22:32)  Повторный вызов не схлопотать. Запрещаются все приоритеты равные и ниже текущего. А то, что нельзя делать одинаковые приоритеты я и сам жалею. Помню как удобно было на 51/52 процах с трёхуровневой системой прерываний. Быстро и удобно.
В данном вопросе только один минус - лишняя многоуровневость. Но гораздо больше плюсов. Особенно быстрое время реакции на все прерывания с учётом приоритетов. А медленные софтверные прерывания вообще не сделать без вложенности.
Не-а. Я бы советовал не использовать обычные прерывания без особой необходимости. Особенно длинные или использующие много стека. Повторный вызов можно схлопотать элементарно. VicVectAddr=0 открывает ВСЕ прерывания. Нужно явно маскировать и восстанавливать приоритеты.
|
|
|
|
|
Jun 19 2009, 09:11
|
Группа: Новичок
Сообщений: 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 должен быть использован для правильной реализации вложенности.
|
|
|
|
|
Jun 19 2009, 10:07
|
Гуру
     
Группа: Свой
Сообщений: 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.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|