|
Приоритет прерываний в AVR, что он означет? |
|
|
|
Aug 12 2010, 06:19
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
В даташитах этот термин есть, но написано лишь что прерывания с меньшим номеров имеют больший приоритет. А что вообще означает это слово? Я считал, что в подобных системах (имеющих лишь один бит в регистре состояния для разрешения/запрещения прерываний) это означает, что если возникнут одновременно два прерывания, то первым будет обрабатываться то, которое имеет больший приоритет. Во во время его обработки бит I сбрасывается, но если выполнить sei, то мы разрешим обработку других прерываний, в том числе и с меньшим приоритетом. Просто потому, что процессор не знает, что он в нанный момент делает - выполняет обработку прерывания или основную программу. Нет у него битов определить это.
Однако сейчас, отлаживая устройство, я обнаружил странную вещь - прерывание таймера не прерывается UART-ом. Обработка UART-а задерживается независимо от того, ставлю ли я sei в начале подпрограммы обработки таймера или не ставлю. Может ли такое быть или у меня глюки? И если может, то как разрешить прерывать таймер во время его обработки?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 21)
|
Aug 12 2010, 06:29
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Вы о сохранении и восстановлении SREG -а забываете
Причина редактирования: Бездумное цитирование
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Aug 12 2010, 07:02
|

Профессионал
    
Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409

|
Цитата(777777 @ Aug 12 2010, 09:19)  Однако сейчас, отлаживая устройство, я обнаружил странную вещь - прерывание таймера не прерывается UART-ом. Обработка UART-а задерживается независимо от того, ставлю ли я sei в начале подпрограммы обработки таймера или не ставлю. Может ли такое быть или у меня глюки? И если может, то как разрешить прерывать таймер во время его обработки? При разрешении прерываний внутри обработчика прерываний будут выполняться другие возникшие в этот момент прерывания. Но как Вам написали выше в кажом обработчике прерываний необходимо сохранять и восстанавливать состояние регистра SREG. Снизу пример обработчика перываний от UART сгенерированный IARом. Он в каждом прерывании сохраняет и восстанавливает состояние SREG. CODE \ __nearfunc __version_3 __interrupt void USART0_RX_IRQ() \ ??USART0_RX_IRQ: \ 00000000 93FA ST -Y, R31 \ 00000002 93EA ST -Y, R30 \ 00000004 934A ST -Y, R20 \ 00000006 933A ST -Y, R19 \ 00000008 932A ST -Y, R18 \ 0000000A 931A ST -Y, R17 \ 0000000C 930A ST -Y, R16 \ 0000000E B74F IN R20, 0x3F //тут IAR сохраняет SREG \ 00000010 910000C6 LDS R16, 198 \ 00000014 .... LDI R30, LOW(Rx0Head) \ 00000016 .... LDI R31, (Rx0Head) >> 8 \ 00000018 8120 LD R18, Z \ 0000001A 8131 LDD R19, Z+1 \ 0000001C 01F9 MOVW R31:R30, R19:R18 \ 0000001E .... SUBI R30, LOW((-(Rx0Buf) & 0xFFFF)) \ 00000020 .... SBCI R31, (-(Rx0Buf) & 0xFFFF) >> 8 \ 00000022 8300 ST Z, R16 \ 00000024 .... LDI R30, LOW(Rx0Head) \ 00000026 .... LDI R31, (Rx0Head) >> 8 \ 00000028 8100 LD R16, Z \ 0000002A 8111 LDD R17, Z+1 \ 0000002C 5F0F SUBI R16, 255 \ 0000002E 4F1F SBCI R17, 255 \ 00000030 8300 ST Z, R16 \ 00000032 8311 STD Z+1, R17 \ 00000034 8100 LD R16, Z \ 00000036 8111 LDD R17, Z+1 \ 00000038 3400 CPI R16, 64 \ 0000003A E020 LDI R18, 0 \ 0000003C 0712 CPC R17, R18 \ 0000003E F010 BRCS ??USART0_RX_IRQ_1 \ 00000040 8320 ST Z, R18 \ 00000042 8321 STD Z+1, R18 \ ??USART0_RX_IRQ_1: \ 00000044 BF4F OUT 0x3F, R20 //тут IAR восстанавливает SREG \ 00000046 9109 LD R16, Y+ \ 00000048 9119 LD R17, Y+ \ 0000004A 9129 LD R18, Y+ \ 0000004C 9139 LD R19, Y+ \ 0000004E 9149 LD R20, Y+ \ 00000050 91E9 LD R30, Y+ \ 00000052 91F9 LD R31, Y+ \ 00000054 9518 RETI
Сообщение отредактировал mempfis_ - Aug 12 2010, 07:03
|
|
|
|
|
Aug 12 2010, 07:21
|

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

|
Цитата(777777 @ Aug 12 2010, 11:10)  Разумеется SREG сохраняется и восстанавливается, но при чем тут он? В нем есть биты, которые могут запретить прерывания UART-а во время обработки таймера? Даже когда глобальные прерывания разрешены? Код предельно простой (WinAVR): Код ISR(TIMER0_COMPA_vect) { asm("sei"); // дальше обработка таймера // может ли она прерваться если сейчас придет прерывание от UART? // судя по поведению устройства - нет В WinAVR есть SIGNAL, который сам разрешит вложенные прерывания. Код SIGNAL(TIMER0_COMPA_vect) { ......... }
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Aug 12 2010, 07:32
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(dimka76 @ Aug 12 2010, 11:21)  В WinAVR есть SIGNAL, который сам разрешит вложенные прерывания. Ты что-то путаешь. Цитата Global SIGNAL Do not use SIGNAL() in new code. Use ISR() instead. И ничего про вложенные прерывания.
|
|
|
|
|
Aug 12 2010, 07:45
|

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

|
Цитата(777777 @ Aug 12 2010, 11:32)  Ты что-то путаешь. И ничего про вложенные прерывания. Извиняюсь, действительно перепутал. Полистал сейчас avr-libc-usert-manual и наткнулся вот на какую вещь Цитата 22.15.2.9 #define ISR_NOBLOCK # include <avr/interrupt.h> ISR runs with global interrupts initially enabled. The interrupt enable flag is activated by the compiler as early as possible within the ISR to ensure minimal processing delay for nested interrupts. This may be used to create nested ISRs, however care should be taken to avoid stack overflows, or to avoid infinitely entering the ISR for those cases where the AVR hard- ware does not clear the respective interrupt flag before entering the ISR. Use this attribute in the attributes parameter of the ISR macro.
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Aug 12 2010, 07:54
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(GetSmart @ Aug 12 2010, 11:40)  А может таки листинг засветите прологов/эпилогов у обоих прерываний. Прологи/эпилоги обычные, вот например: Код ISR(TIMER0_COMPA_vect) { 37c: 1f 92 push r1 37e: 0f 92 push r0 380: 0f b6 in r0, 0x3f; 63 382: 0f 92 push r0 384: 11 24 eor r1, r1 386: 2f 93 push r18 388: 8f 93 push r24 38a: 9f 93 push r25 и т.д. Только зачем это? Я всего лишь хотел узнать, можно ли сделать чтобы прерывание от UART могло прервать прерывание таймера. То, что вложенные прерывания возможны в принципе, я знаю, в другой программе АЦП успешно прерывается другими прерываниями, но у него и приоритет ниже. Так может приоритет - это не только порядок в котором будут обрабатываться одновременно пришедшие прерывания, но и невозможность прервать более высокоприоритетное устройство низкоприоритетным? Цитата(dimka76 @ Aug 12 2010, 11:45)  Извиняюсь, действительно перепутал. Полистал сейчас avr-libc-usert-manual и наткнулся вот на какую вещь #define ISR_NOBLOCK Да, есть такое. Этот ISR в самом начале вставляет sei. Это лучше, чем вставлять его после сохранения регистров, но на мою программу это не повлияло - UART так и не прерывает таймер.
|
|
|
|
|
Aug 12 2010, 08:14
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Я всю жизнь думал, что у AVR-ов нет аппаратных приоритетов вложенных прерываний, есть только приоритеты для выбора ещё не обработанных, но активных прерываний. И ни разу не сталкивался с чем-то не подчиняющимся этим правилам. Поэтому и исчу косяк. Но могу и проверить при случае в железе. CODE adc_rdy_irq: SEI PUSH R16 IN R16,SREG PUSH R16 LDI R16,255 STS AdcStruc+48,R16 POP R16 OUT SREG,R16 POP R16 RETI Проверил в своей проге. Всё так, как и предполагал. Из прерывания T2COMP при разрешённых прерываниях свободно вызывается прерывание ADC_RDY, у которого приоритет намного ниже. проц Mega8L
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Aug 12 2010, 16:45
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(GetSmart @ Aug 12 2010, 17:50)  .... Главное, что из обрабатывающегося прерывания с высоким приоритетом вызывается более низкоприоритетное, это точно. Согласен, да и в DS описывается , что сбрасывается только флаг I и ни где не описывается , что при обработки прерывания , оно блокирует ещё что-то кроме этого флага. Но при возникновении двух разноприоритетных прерываний , при разрешёном вложенном прерывании, обработается старшее по приоритету. Может это и происходит у 777777 т.е до нужного дело не доходит
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Aug 13 2010, 05:23
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(Блин. Побрился клоками :( @ Aug 12 2010, 22:29)  При возникновении разрешённого прерывания сбрасывается влаг глобального разрешения прерываний в SREG и осуществляется переход на процедуру обработки прерывания по соответствующему вектору. Если в обработчике прерываний "вручную" установить флаг глобального разрешения прерываний в SREG, то возможно получить вложенные прерывания. Причём более "низко" приоритетное может прервать более "высоко" приоритетное прерывание. А кто с Вами спорит или этого не знал? LOL Хотя о приоритетах это Вы зря. В АВР есть номера векторов прерываний на каждый МК и от него зависит так званый Ваш "приоритет"
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Aug 13 2010, 13:10
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(777777 @ Aug 12 2010, 11:54)  Да, есть такое. Этот ISR в самом начале вставляет sei. Это лучше, чем вставлять его после сохранения регистров... Это не только лучше, но и хуже т.к. в компиляторе похоже бага по части ISR_NOBLOCK:(. Он поступает ровно так как Вы и сказали - тупо ставит sei в самом начале обработчика. А если у вас в обработчике есть стековые переменные - всё может пойти в тар-тарары.. Т.к. он модифицирует указатель стека не в критической секции (забыв что прерывания уже разрешены) Код 280 0116 DEBF out __SP_H__,r29 282 011a CDBF out __SP_L__,r28 а должен бы так: Код 278 0112 0FB6 in __tmp_reg__,__SREG__ 279 0114 F894 cli 280 0116 DEBF out __SP_H__,r29 281 0118 0FBE out __SREG__,__tmp_reg__ 282 011a CDBF out __SP_L__,r28 Для решения сей баги есть стандартный ход: Код ISR(MY_ISR) { sei();
code....
cli(); } Цитата(Блин. Побрился клоками :( @ Aug 12 2010, 23:29)  Вообщем так, молодёжь! Объясняю на пальцах. При возникновении разрешённого прерывания сбрасывается влаг глобального разрешения прерываний в SREG и осуществляется переход на процедуру обработки прерывания по соответствующему вектору. Если в обработчике прерываний "вручную" установить флаг глобального разрешения прерываний в SREG, то возможно получить вложенные прерывания. Согласен. Цитата Причём более "низко" приоритетное может прервать более "высоко" приоритетное прерывание. Не согласен. Все остальные разрешённые прерывания могут прервать выполнение текущей ISR с вручную установленным флагом I внутри этой ISR.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 17 2010, 03:52
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата Код adc_rdy_irq: SEI PUSH R16 IN R16,SREG PUSH R16 LDI R16,255 STS AdcStruc+48,R16 POP R16 OUT SREG,R16 POP R16 RETI Заметил ошибку. Разрешать прерывания в прерываниях надо ТОЛЬКО после сохранения SREG!!!! Код adc_rdy_irq: PUSH R16 IN R16,SREG PUSH R16 SEI ; !!!!!!!!!!!!!!!!!!!!!!!!!!! LDI R16,255 STS AdcStruc+48,R16 POP R16 OUT SREG,R16 POP R16 RETI
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|