Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2017-авг-17 08:46

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
 Заголовок сообщения: Сохранение FSR0 в прерывании
СообщениеДобавлено: 2015-сен-11 16:32 
Не в сети

Зарегистрирован: 2015-фев-09 08:45
Сообщения: 5
Понадобилось работать с массивами в обработчике прерываний, и компилятор выдал ошибку "FSR0 not saved/restored during interrupt".
Эта проблема решилась правкой файла INT17XXX.H, как сказано здесь: http://forum.milandr.ru/viewtopic.php?f=4&t=484#p11286

Однако после этой правки возникла другая проблема - иногда в основной программе при считывании данных из массивов происходят ошибки (считываются не те данные), в том случае, если включены прерывания.
Расскажу немного подробнее о тестовой программе, в которой возникают ошибки.
Прерывания в данном случае создает таймер 1, частота прерываний - 600 Гц, в обработчике прерываний таймера - просто цикл с nop().
Код:
if (TMR1IF)
{
  TMR1IF = 0;
  for (timer1_test = 0;timer1_test<50;timer1_test++) nop();
}


Основная программа периодически отправляет по UART на компьютер содержимое двух массивов (заполняются при включении контроллера):
Код:
for (i8=0;i8<200;i8++){uart2_send_byte(rx_array[i8]);}
for (i8=0;i8<200;i8++){uart2_send_byte(rx_array2[i8]);}


При этом, если включены прерывания, иногда некоторые на компьютер приходят неверные одиночные байты. Если прерывания таймера выключены, то ошибок нет.

Если код переделать вот так (так нужно в реальной программе):
Код:
     tx_pos = 0;
     for (i8=0;i8<100;i8++)
     {
        send_4bytes(tx_pos);
        tx_pos+=4;
     }
//*********************
void send_4bytes(uns16 ltx_cnt)
{
     unsigned char ltx_pos;
     unsigned char buffer;
     
     if (ltx_cnt < 200)
     {
        ltx_pos = (unsigned char)(ltx_cnt);
        buffer = 0;
     }
     else
     {
        ltx_pos = (unsigned char)(ltx_cnt - 200);
        buffer = 1;
     }
     //GLINTD = 1;//Interrupts disable
     if (buffer == 0)
     {
      uart2_send_byte(rx_array[ltx_pos]);
      uart2_send_byte(rx_array[ltx_pos+1]);
      uart2_send_byte(rx_array[ltx_pos+2]);
      uart2_send_byte(rx_array[ltx_pos+3]);
     }
     else
     {
      uart2_send_byte(rx_array2[ltx_pos]);
      uart2_send_byte(rx_array2[ltx_pos+1]);
      uart2_send_byte(rx_array2[ltx_pos+2]);
      uart2_send_byte(rx_array2[ltx_pos+3]);
     }     
     //GLINTD = 0;//Interrupts enable
}

то частота ошибок возрастает раз в 10.
Если раскомментировать выключение и включение прерываний в функции send_4bytes, то ошибки полностью исчезают.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сохранение FSR0 в прерывании
СообщениеДобавлено: 2015-сен-11 17:18 
Не в сети

Зарегистрирован: 2010-апр-27 15:10
Сообщения: 8
Откуда: АО "ПКК Миландр"
iliasam писал(а):
Понадобилось работать с массивами в обработчике прерываний, и компилятор выдал ошибку "FSR0 not saved/restored during interrupt".
Эта проблема решилась правкой файла INT17XXX.H, как сказано здесь: http://forum.milandr.ru/viewtopic.php?f=4&t=484#p11286


По ссылке выше приведена не совсем корректная подпрограмма сохранения регистров. По вектору прерывания 0х08 FSR0 сохраняется корректно, но в случае других векторов прерывания, одним из которых, кстати, таймер и является, FSR0 не сохраняется, но восстанавливается в конце прерывания непредсказуемым значением из регистра .

Для корректной работы, стоит изменить этот код, как указано ниже:

Код:
#define  multi_interrupt_entry_and_save \
    shrBank char sBSR, sALUSTA; \
    bank0 char sWREG, sPCLATH, THP; \
        \
   #asm \
    ; ADDRESS 0x08 \
    MOVFP BSR,sBSR           ; unbanked \
    MOVFP ALUSTA, sALUSTA    ; unbanked \
    CLRF BSR \
    MOVPF PCLATH, sPCLATH    ; bank 0 \
    MOVWF sWREG              ; bank 0 \
    MOVPF FSR0, THP  \
    CLRF PCLATH \
    GOTO INT_service \
    NOP \
         \
    ; ADDRESS 0x10 \
    MOVFP BSR,sBSR           ; unbanked \
    MOVFP ALUSTA, sALUSTA    ; unbanked \
    CLRF BSR \
    MOVPF PCLATH, sPCLATH    ; bank 0 \
    MOVWF sWREG              ; bank 0 \
    MOVPF FSR0, THP  \        ; !!!!!!!!!!!!!!!!!!!!!!!!!Вставить эту строчку!!!!!!!!!!!!!!!!!!!
    CLRF PCLATH \
    GOTO TMR0_service \
    NOP \
        \
    ; ADDRESS 0x18 \
    MOVFP BSR,sBSR           ; unbanked \
    MOVFP ALUSTA, sALUSTA    ; unbanked \
    CLRF BSR \
    MOVPF PCLATH, sPCLATH    ; bank 0 \
    MOVWF sWREG              ; bank 0 \
    MOVPF FSR0, THP  \        ; !!!!!!!!!!!!!!!!!!!!!!!!!Вставить эту строчку!!!!!!!!!!!!!!!!!!!
    CLRF PCLATH \
    GOTO T0CKI_service \
    NOP \
        \
    ; ADDRESS 0x20 \
    MOVFP BSR,sBSR           ; unbanked \
    MOVFP ALUSTA, sALUSTA    ; unbanked \
    CLRF BSR \
    MOVPF PCLATH, sPCLATH    ; bank 0 \
    MOVWF sWREG              ; bank 0 \
    MOVPF FSR0, THP  \        ; !!!!!!!!!!!!!!!!!!!!!!!!!Вставить эту строчку!!!!!!!!!!!!!!!!!!!
    CLRF PCLATH \
   #endasm \
    goto PERIPHERAL_service; \


Код:
#define interrupt_exit_and_restore \
   #asm \
      MOVFP THP, FSR0 \
    MOVFP sWREG,W            \
    MOVFP sPCLATH, PCLATH    \
    MOVFP sALUSTA, ALUSTA    \
    MOVFP sBSR, BSR          \
    RETFIE \
   #endasm \


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сохранение FSR0 в прерывании
СообщениеДобавлено: 2015-сен-14 10:03 
Не в сети

Зарегистрирован: 2015-фев-09 08:45
Сообщения: 5
Большое спасибо, заработало!
Хотя пришлось выкинуть NOP - насколько я понял, между векторами прерываний должно быть по 8 команд.
Получившийся рабочий код:
Цитата:
#define multi_interrupt_entry_and_save \
shrBank char sBSR, sALUSTA; \
bank0 char sWREG, sPCLATH, THP; \
\
#asm \
; ADDRESS 0x08 \
MOVFP BSR,sBSR ; unbanked \
MOVFP ALUSTA, sALUSTA ; unbanked \
CLRF BSR \
MOVPF PCLATH, sPCLATH ; bank 0 \
MOVWF sWREG ; bank 0 \
MOVPF FSR0, THP \
CLRF PCLATH \
GOTO INT_service \
;NOP \
\
; ADDRESS 0x10 \
MOVFP BSR,sBSR ; unbanked \
MOVFP ALUSTA, sALUSTA ; unbanked \
CLRF BSR \
MOVPF PCLATH, sPCLATH ; bank 0 \
MOVWF sWREG ; bank 0 \
MOVPF FSR0, THP \
CLRF PCLATH \
GOTO TMR0_service \
;NOP \
\
; ADDRESS 0x18 \
MOVFP BSR,sBSR ; unbanked \
MOVFP ALUSTA, sALUSTA ; unbanked \
CLRF BSR \
MOVPF PCLATH, sPCLATH ; bank 0 \
MOVWF sWREG ; bank 0 \
MOVPF FSR0, THP \
CLRF PCLATH \
GOTO T0CKI_service \
;NOP \
\
; ADDRESS 0x20 \
MOVFP BSR,sBSR ; unbanked \
MOVFP ALUSTA, sALUSTA ; unbanked \
CLRF BSR \
MOVPF PCLATH, sPCLATH ; bank 0 \
MOVWF sWREG ; bank 0 \
MOVPF FSR0, THP \
CLRF PCLATH \
#endasm \
goto PERIPHERAL_service; \


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB