Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обработка двух прерываний ?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
zombi
Столкнулся с проблемой.
Долго мучался и ветаки поборол, но как-то странно!

Опишу кратко.
Используется два прерывания:

1:0x01A Timer/Counter1 Compare Match A - режим CLC (частота 44100 Hz)
2:0x020 Timer/Counter0 Compare Match - режим CLC ( частота 500 Hz)

У второго прерывания приоритет ниже и первая команда его обработчика SEI.
Все регистры и флаги сохраняются в каждом обработчике.
Проблема в том что во втором прерывании необходимо читать состояние PIND.4
Состояние пина иногда считывается 0-м в то время как он в 1-це.

В таком виде глючило:

CBI PORTB,7
SBI PORTB,7
ROL RTMP
SBIC PIND.4
ANDI RTMP,$01

добавил запрет и разрешение прерываний и глюк ПОЛНОСТЬЮ пропал:

CLI
CBI PORTB,7
SBI PORTB,7
ROL RTMP
SBIC PIND.4
ANDI RTMP,$01
SEI

Что это, глюк меги или я чегото не понимаю?
Ктонибудь сталкивался с подобным?
_Pasha
Цитата(zombi @ Jan 27 2009, 16:09) *
CLI
CBI PORTB,7
SBI PORTB,7
ROL RTMP
SBIC PIND.4
ANDI RTMP,$01
SEI
Что это, глюк меги или я чегото не понимаю?

Это глюк автора программы, вероятно, забывшего о необходимости сохранять SREG. smile.gif
Впрочем - это чистая телепатия, потому что из того, что Вы написали, вообще понять ничего невозможно. Дайте больше информации.
zombi
Я ж написал что "Все регистры и флаги сохраняются в каждом обработчике.
"
Цитата
Дайте больше информации.

Попробую.
Вся проблема в том что если во время приведенных мою 5-ти команд 2-го обработчика выполняется другое прерывание то состояние 4-го пина порта D командой CBIC интерпретируется не верно.
_Pasha
Цитата(zombi @ Jan 27 2009, 16:09) *
У второго прерывания приоритет ниже и первая команда его обработчика SEI.
Все регистры и флаги сохраняются в каждом обработчике.
В стеке? Код полностью огласите плз.
zombi
Цитата
В стеке? Код полностью огласите плз.

Полность очень много!
Попробую частями.
Настройка и разрешение прерываний:
Код
;-- TIMER1 - SOUND --------------
    LDI    RTMP,$09
    OUT    TCCR1B,RTMP
    LDI    RTMP,HIGH(362)
    OUT    OCR1AH,RTMP
    LDI    RTMP,LOW(362)
    OUT    OCR1AL,RTMP

;-- TIMER0 - KEY --------------
    LDI    RTMP,$0E
    OUT    TCCR2,RTMP
    LDI    RTMP,124
    OUT    OCR2,RTMP
;-----------------
    LDI    RTMP,$50
    OUT    TIMSK,RTMP

Обработчик timer1:
Код
TIM1:
    PUSH    RTMPA
    IN    RTMPA,$3F
    PUSH    RTMPA
.
.
.
    POP    RTMPA
    OUT    $3F,RTMPA
    POP    RTMPA
    RETI

Обработчик timer0:
Код
TIM0:
    SEI
    PUSH    RTMPA
    IN    RTMPA,$3F
    PUSH    RTMPA
.
.
.
    CLI      <----------------------
    CBI    PORTB,7
    SBI    PORTB,7
    LSL    RTMPA
    SBIC    PIND,4
    ORI    RTMPA,$01
    SEI     <----------------------
.
.
.
    STS    $8000,RTMPA
    RET


Проблема в том что даже если на PIND.4 тупо VCC подать, то младший бит в ячейке $8000 не всегда =1 если в обработчике TIM0 нету CLI/SEI во время его опроса.
_Pasha
Опускаю Ваши небрежности (код выхода из TIM0, код инициализации TIM0) - я так понял, что в реале там все нормально ?
Несогласен раз:
Код
TIM0:

;*************
    CBI    PORTB,7
    SBI    PORTB,7
    LSL    RTMPA
    CLI      <----------------------
   SBIC    PIND,4
    ORI    RTMPA,$01
    SEI     <----------------------
;*****

Несогласен, часть вторая: пожертвуйте регистром 
Код
in RTMPC,PIND
bst RTMPC,4
bld RTMPA,0

ЗЫ марш несогласных smile.gif
Раньше была проблема такая с sbrc/sbic sbrs/sbis но это было давно.
defunct
Цитата(zombi @ Jan 27 2009, 15:23) *
Попробую частями.
Код
TIM0:
    SEI
    PUSH    RTMPA
    IN    RTMPA,$3F
    PUSH    RTMPA


Может происходит повторный вызов TIM0? Вы же не запрещаете "ЭТО" прерывание.

Пропробуйте так:
Код
TIM0:
    cbi     TIMSK, OCIE0
    sei
....
    sbi   TIMSK, OCIE0
    reti
zombi
Спасибо всем ответившим.
Цитата
пожертвуйте регистром но это было давно

Через рег тоже пробывал, не помогло.
Цитата
Опускаю Ваши небрежности (код выхода из TIM0, код инициализации TIM0) - я так понял, что в реале там все нормально ?

А что с выходом из TIM0? Если вы имеете ввиду RET а не RETI то я же прерывания разрешаю в теле обратотчика.

Ув. _Pasha подскажите что не правильно в инициализации TIM0?
Просто я всегда так инициализирую, подскажите где ошибка.

Цитата
Может происходит повторный вызов TIM0? Вы же не запрещаете "ЭТО" прерывание

Незнаю. Надо попробывать . Спасибо defunct.
Но думаю что прерывание должно срабатывать по фронту?
Но даже еслиб вход выполнялся несколько раз то в мл.бите регистра RTMPA всеравно должна быть единица ведь состояние PIND.4 стабильно.

Цитата(defunct @ Jan 27 2009, 18:20) *
Может происходит повторный вызов TIM0? Вы же не запрещаете "ЭТО" прерывание.

Пропробуйте так:
Код
TIM0:
    cbi     TIMSK, OCIE0
    sei
....
    sbi   TIMSK, OCIE0
    reti

Попробывал. Результат отрицательный. Глюки продолжаются.


Цитата(_Pasha)
Код
TIM0:

;*************
    CBI    PORTB,7
    SBI    PORTB,7
    LSL    RTMPA
    CLI      <----------------------
   SBIC    PIND,4
    ORI    RTMPA,$01
    SEI     <----------------------
;*****

И так пробывал но тоже глючит.
Глюки исчезают только если CLI находится перед LSL или еще раньше, но никак не перед SBIC:
Код
;*************
    CBI    PORTB,7
    SBI    PORTB,7
    CLI      <----------------------
    LSL    RTMPA
   SBIC    PIND,4
    ORI    RTMPA,$01
    SEI     <----------------------
;*****
_Pasha
Цитата(zombi @ Jan 27 2009, 18:16) *
А что с выходом из TIM0? Ув. _Pasha подскажите что не правильно в инициализации TIM0?

1.Инициализация
Код
;-- TIMER0 - KEY --------------
    LDI    RTMP,$0E
    OUT    TCCR2,RTMP
    LDI    RTMP,124
    OUT    OCR2,RTMP


Мы говорим о прерывании таймера 0, а здесь и далее у Вас инициализация таймера 2. Если эта небрежность все-же имеет отношение  к проблеме, то проверьте таблицу векторов прерываний - вполне возможно, что там бардак.

2. Код входа и выхода 
Код
   
SEI
PUSH    RTMPA
IN        RTMPA,SREG
PUSH        RTMPA
; *******

STS  $8000,RTMPA

pop   RTMPA
out    SREG,RTMPA
pop   RTMPA 
reti
zombi
Цитата
то проверьте таблицу векторов прерываний - вполне возможно, что там бардак.

Конечно с таблицей векторов и POPами PUSHами все впорядке.
Это просто апычатки laughing.gif sorry.
_Pasha
Значит где-то чистят Ваш RTMPA без сохранения/восстановления. Поставьте условный брекпоинт на запись в регистр и дебажьте до победы.
zombi
Цитата(_Pasha @ Jan 27 2009, 19:30) *
Значит где-то чистят Ваш RTMPA без сохранения/восстановления. Поставьте условный брекпоинт на запись в регистр и дебажьте до победы.

Не думаю что я гдето порчу RTMPA ведь с CLI/SEI нечего не портится!!!
Всетаки мне кажется проблема с входом в прерывание в момент выполнения SBIC/S возможно даже именно с PIND.4.
В любом случае экспериментировать надоело , запрет/разрешение прерываний спасает и пару лишних тактов не жмет, работает и бог с ним. rolleyes.gif
SasaVitebsk
Интересно.
Я не сталкивался, но в первых моделях указывали про ошибки возникающие именно при прерывании и именно при исполнении комад sbic/sbis. Правда, если команда следующая за этими командами - двухсловная.
При этом про команды BLD/BST никогда ничего не было.

Всётаки я думаю, что вам надо исходить из постулата, что это ваша ошибка. И, соответственно, искать её корни. Иначе она вылезет в другом месте и в другом виде. А заплатки ставить - не пацанский метод.
uau
Цитата(zombi @ Jan 27 2009, 18:16) *
А что с выходом из TIM0? Если вы имеете ввиду RET а не RETI то я же прерывания разрешаю в теле обратотчика.


А из стека, кто байт флагов будет вычищать?
zombi
Прошу прощения за поднятую бучу!
Все оказалось гораздо проще.
Ко входу D.4 подключен выход сдвигового регистра 74hc157.
Опрос пина был сразу после строба SCK и регистр просто не успевал переключится.
Частота процессора 16MHz а у регистра время установления выхода большое вот от он то успевал то нет.
А команда CLI просто добавляла необходимую задержку laughing.gif

Но благодаря defunct возможно сразу избежал следующего косяка с прерываниями:
Если время выполнения прерывания TIM1 окажется больше чем период TIM2 то возможен повторный вход в в TIM2.
Устранил эту ситуацию запретом прерывания по TIM2 путем записи в TIMSK на старте и последующим разрешением на выходе.
Код
TIM2:    PUSH    RTMPA
    LDI    RTMPA,$40
    OUT    TIMSK,RTMPA
    SEI
    IN    RTMPA,SREG
    PUSH    RTMPA
    .
    .
    .
    POP    RTMPA
    OUT    SREG,RTMPA
    LDI    RTMPA,$50
    CLI
    OUT    TIMSK,RTMPA
    POP    RTMPA
    RETI
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.