Всем привет. Поиском по форуму не нашел, опишу свою проблему, на решение которой ухлопана неделя.
Вдруг еще кто столкнется.
PIC16F876A. Делал динамическую индикацию на семисегментных индикаторах. Чтобы она не мешала основной программе, оформил ее в виде прерывания. Сначала сделал прерывание средствами PicBasic Pro (ON INTERRUPT), все работает нормально, но индикатор помаргивает, т.к. PICBASIC проверяет прерывания только после окончания очередного оператора, а они в основной программе длинные попадаются. Ладно, вспомним старый добрый ассемблер. Переписываю прерывание на ассемблере, читаю раздел из мануала PICBasic про то, как нужно вставлять прерывания на ассемблере, про сохранение и восстановление аккумулятора и регистров STATUS и PCLATH. Вроде все понял, вставляю в начало и конец прерывания соответствующие конструкции (прямо из примера asmint.bas):
; Save W, STATUS and PCLATH registers, if not done previously
myint movwf wsave
swapf STATUS, W
clrf STATUS
movwf ssave
movf PCLATH, W
movwf psave
;---- тут обработчик прерывания --------
; Restore saved registers
movf psave, W
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W
retfie ; Return from interrupt
Естественно, при описании переменных были заданы:
wsave var byte $20 system
wsave1 var byte $a0 system ' Necessary for devices with RAM in bank1
wsave2 var byte $120 system ' Necessary for devices with RAM in bank2
wsave3 var byte $1a0 system ' Necessary for devices with RAM in bank3
ssave var byte bank0 system
psave var byte bank0 system
Компилирую это все, исправляю пару мелких ошибок в асмовском прерывании и все - вроде работает
индикация, не помаргивает. Но...
И вот тут началось. Сначала, когда в основной программе был только оператор присвоения переменной значения, подлежащего выводу на индикатор, все было хорошо. Затем, по мере увеличения числа операторов в основной программе на индикаторе стали проскакивать символы, которые я туда не отправлял. А затем и вообще вся программа начала виснуть. Эпизодически...
Неделя поиска глюка толку не дала. Прошуршал и microchip.su, и ваш форум. На Вашем форуме у пользователя HolyUser нашел пример SampleClock.rar, в котором использованы прерывания на ассемблере. Все как по мануалу...
И только сегодня, в десятый раз читая раздел по асмовским прерывания, до меня дошел смысл фразы:
If a 14-bit core PICmicro MCU has more than 2K of code space, an
interrupt stub is automatically added that saves the W, STATUS and
PCLATH registers into the variables wsave, ssave and psave, before
going to your interrupt handler.
Подтвердили догадку комментарии в последующем примере:
; Save W, STATUS and PCLATH registers
myint movwf wsave ; <= 2K only
swapf STATUS, W ; <= 2K only
clrf STATUS ; <= 2K only
movwf ssave ; <= 2K only
movf PCLATH, W ; <= 2K only
movwf psave ; <= 2K only
То есть в ПИКах серии 16ххх с объемом программной памяти 2 килослова и менее в начале прерывания нужно сохранять регистры, а в пиках с объемом более 2К сам компилятор вставляет строчки из вышеприведенного примера в компилируемый файл. При этом команды восстановления регистров при выходе из прерывания должны присутствовать для всех типов пиков.
Таким образом, я на входе в прерывание сохранял регистры, которые предварительно уже сохранил сам компилятор (и очистил STATUS).
Ну скажите, какому ИДИОТУ-разработчику пришла в голову мысль только для ПИКОВ > 2K АВТОМАТИЧЕСКИ сохранять регистры при входе в прерывание. Ну сделали бы стандартно, для всех ПИКОВ эту заглушку и не описывали ее в мануале. Или, еще лучше ничего бы не делали, заботиться о сохранении регистров должен сам программист на асме.
Неделя убитого времени, блин...
P.S. Сорри за много букофф. Надеюсь, еще кто-нибудь не наступит.