реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> вопрос по работе с тремя прерываниями одинакового приоритета,, которые могут возникнуть одновременно. at91sam7s
Bulat
сообщение Nov 23 2009, 12:49
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



по прерыванию от порта PIO считываются последовательные данные, то есть при каждом прерывании считывается один бит:
Код
__ramfunc void irq_Receive()
{
  PauseTimerBase->TC_CCR = AT91C_TC_CLKEN;  
  PauseTimerBase->TC_CCR = AT91C_TC_SWTRG;                                    

  source = regs->PIOA_PDSR&0x600;
    
  if(source==0x200) {recA = recA>>1;  i_shA++; recA = recA|0x80000000;} //A1
  if(source==0x400) {recA = recA>>1;  i_shA++; recA = recA&0x7FFFFFFF;}  //B1
  
   dummy = AT91C_BASE_PIOA->PIO_ISR;    
}

при этом перезапускается таймер, который остчитывает паузу между принимаемыми словами. как только пришла пауза, таймер срабатывает и по прерыванию:
Код
__ramfunc void pause_timer_irq()
{
  if(i_shA==32)
  {
    recDA[kA] = recA; kA++;    
  }  
  if(kA==12)  send_to_host();  
  i_shA=0;
  dummy = PauseTimerBase->TC_SR;  
}

записывает данные в некий буфер.
но помимо этого одновременно может идти передача данных по прерываниюот другого таймера, работающего в режиме генератора:
Код
__ramfunc void timer0_irq_handler()
{  
  ii--;                                                                         //счетчик переданных бит
  if(ii==1) {MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS;}
  MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60;
  if(datA&0x80000000) regA = 0x20000;
  else regA = 0x0;
  regs->PIOA_ODSR = regA|front;      
  datA = datA<<1;
  dummy = MipsTimerBase->TC_SR;
  
}

Передача и прием идут с частотой 100 кГц. Приоритеты всех прерываний 7, то есть по идее они должны выполняться по очереди. Но при этом обработчик таймера паузы должен успеть все сделать до прихода следующего слова.
Передача и прием по отдельности работают нормально, без сбоев. Но при их одновременной работе прием не нарушается, а передача происходит с ошибками и в дальнейшем вовсе останавливается. Поэтому я и решил оптимизировать обработчики прерываний.
Для начала я решил все обработчики поместить в RAM, но тут столкнулся с интересной особенностью, если обработчик приемника void irq_Receive() не помещать в ОЗУ, то прием идет очень медленно, не успевает. Но, если обработчик передатчика void timer0_irq_handler() поместить в ОЗУ, то при одновременной работе приемника и передатчика (замыкание выхода передатчика на вход приемника) данные вообще не передаются, а если не помещать в ОЗУ то немного данных передаются. Как правильно размещать обработчики прерываний в ОЗУ и значительно ли это ускоряет работу?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 23 2009, 15:23
Сообщение #2


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



А где код, который вызывает все эти обработчики? У них общий хэндлер?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 04:44
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(GetSmart @ Nov 23 2009, 20:23) *
А где код, который вызывает все эти обработчики? У них общий хэндлер?

Структура программы следующая:
Код
//Обработчик прерывания таймера 1 - контроллер паузы между принимаемыми словами
__ramfunc void pause_timer_irq()
{
  - запись принятого 32-битного слова в буфер;
}

//Прием последовательности бит по прерыванию от порта PIO
__ramfunc void irq_Receive()
{
   - запуск таймера 1, контролирующего паузу;
   - прием последовательности бит по прерыванию от порта PIO
}

//Передача последовательности бит по прерыванию от таймера 0
__ramfunc void timer0_irq_handler()
{  
  ii--;  //счетчик переданных бит
  ...
}

//Команда на передачу данных
void Write_TRA()
{
   - подготовка данных для передачи по послед каналу;
   - запуск таймера-генератора 0, с пом. которого передаются данные;
   while(ii!=0); //ожидание обнуления счетчика переданных бит (32)
}

void main()
{
   - конфигурирование обработчиков прерывания;
   while(1)  { чтение принятых команд от хоста}
}

Прием и передача идут одновременно с частотой 100 кГц. То есть за 5 мкс необходимо подготовить данные для передачи и выставить их в порт, а за следующие 5 мкс считать данные, которые к тому времени находятся в порту. А во время паузы (40 мкс) надо успеть записать принятое слово в буфер. Для этого я все обработчики помещаю в ОЗУ с помощью __ramfunc. Но при этом какие то сбои происходят при приеме, но когда я убираю из ОЗУ обработчик передатчика timer0_irq_handler, то данные начинают идти, хотя не все... Почему так происходит и как правильно размещать в ОЗУ обработчики прерываний? Все 3 прерывания имеют одинаковый приоритет 7.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 24 2009, 07:15
Сообщение #4


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Ну понятно. Значит ни входа/выхода в прерывание не организовано (__arm __irq), ни сброса VIC/AIC на выходе из прерывания. Удивительно, что что-то вообще работает.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 08:10
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(GetSmart @ Nov 24 2009, 12:15) *
Ну понятно. Значит ни входа/выхода в прерывание не организовано (__arm __irq), ни сброса VIC/AIC на выходе из прерывания. Удивительно, что что-то вообще работает.

так выход же у меня происходит путем считывания статусного регистра dummy = AT91C_BASE_PIOA->PIO_ISR или еще нужно в конце обработчика делать запись AT91C_BASE_AIC->AIC_EOICR = 1 ?
по поводу (__arm __irq), я так делал, но у меня возникала ошибка: Error[Pe167]: argument of type "void (__arm __irq __atpcs *)()" is incompatible with parameter of type "void и компилятор ссылался на функцию конфигурации прерывания: AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, MipsTimer.Id, TIMER_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE, timer0_irq_handler);
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 24 2009, 09:39
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Bulat @ Nov 24 2009, 14:10) *
или еще нужно в конце обработчика делать запись AT91C_BASE_AIC->AIC_EOICR = 1 ?

Именно это должно быть в конце каждого обработчика.
Цитата(Bulat @ Nov 24 2009, 14:10) *
по поводу (__arm __irq), я так делал, но у меня возникала ошибка: Error[Pe167]:

Не знаю что там за проблема, но без __arm __irq (когда нет одного общего на всех хэндлера) нормально прога работать не будет.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 09:43
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Тип преобразуйте:
Код
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, MipsTimer.Id, TIMER_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (void*)timer0_irq_handler);


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

AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE - почему EXT, на кой хрен, простите, EDGE????
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 11:20
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(GetSmart @ Nov 24 2009, 14:39) *
Именно это должно быть в конце каждого обработчика.

Не знаю что там за проблема, но без __arm __irq (когда нет одного общего на всех хэндлера) нормально прога работать не будет.
дело в том, что все это уже прописано в моем стартапе:
-вход в прерывание B IRQ_Handler_Entry ; 0x18 IRQ
- и конец прерывания str r14, [r14, #AIC_EOICR]
Прикрепляю Cstartup.

Цитата(aaarrr @ Nov 24 2009, 14:43) *
Тип преобразуйте:
Код
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, MipsTimer.Id, TIMER_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (void*)timer0_irq_handler);


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

AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE - почему EXT, на кой хрен, простите, EDGE????

Да, извините, тут я упустил. Сейчас во всех 3-х прерываниях поставил AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL.
Только проблема не решилась. А почему у этого контроллера прерывания от порта срабатывают 2 раза - по фронту и по спаду? Для чего тогда ставить AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL или AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE? Может из-за этого контроллер не успевает обработать все прерывания друг за другом. У всех жи одинаковый приоритет.
Прикрепленные файлы
Прикрепленный файл  Cstartup.txt ( 10.21 килобайт ) Кол-во скачиваний: 23
 
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 12:01
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 24 2009, 14:20) *
А почему у этого контроллера прерывания от порта срабатывают 2 раза - по фронту и по спаду?

Потому что так устроен контроллер PIO - генерирует прерывание по любому фронту.

Цитата(Bulat @ Nov 24 2009, 14:20) *
Для чего тогда ставить AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL или AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE?

А для чего вообще работать с внутренними источниками прерываний по фронту?
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 12:18
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Nov 24 2009, 17:01) *
Потому что так устроен контроллер PIO - генерирует прерывание по любому фронту.


А для чего вообще работать с внутренними источниками прерываний по фронту?

Значит я правильно пользуюсь прерываниями с моим стартапом? Конфликтов между прерываниями никаких не может возникнуть в случае одновременного вызова, учитывая, что приоритеты однинаковы?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 12:30
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 24 2009, 15:18) *
Значит я правильно пользуюсь прерываниями с моим стартапом? Конфликтов между прерываниями никаких не может возникнуть в случае одновременного вызова, учитывая, что приоритеты однинаковы?

Правильно - понятие относительное smile.gif Да, пользуетесь правильно: для прерываний не нужны модификаторы __irq и запись EOICR, конфликтов не будет.
Но само по себе использование такого кащенитского стартапа является большой ошибкой.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 12:44
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Nov 24 2009, 17:30) *
Правильно - понятие относительное smile.gif Да, пользуетесь правильно: для прерываний не нужны модификаторы __irq и запись EOICR, конфликтов не будет.
Но само по себе использование такого кащенитского стартапа является большой ошибкой.

то есть из-за этого стартапа могут проблемы возникнуть?
а могут проблемы быть из-за того, что прерывания от порта 2 раза возникают при приходе одного бита? это же дополнительное аремя на вызов и обработку прерывания.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 13:02
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 24 2009, 15:44) *
то есть из-за этого стартапа могут проблемы возникнуть?

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

Цитата(Bulat @ Nov 24 2009, 15:44) *
а могут проблемы быть из-за того, что прерывания от порта 2 раза возникают при приходе одного бита? это же дополнительное аремя на вызов и обработку прерывания.

Вы с оптимизацией разобрались? Пока компилятор генерирует код вроде того, что вчера публиковался, о прерываниях с частотой 100кГц лучше забыть.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 24 2009, 13:11
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Nov 24 2009, 18:02) *
Главная его проблема в том, что он тупо сохраняет контекст и переключает режим для всех подряд прерываний, в том числе и для прерываний с максимальным приоритетом.
В подавляющем большинстве случаев работать будет, просто подобное построение выдает совершенную бездумность подхода.


Вы с оптимизацией разобрались? Пока компилятор генерирует код вроде того, что вчера публиковался, о прерываниях с частотой 100кГц лучше забыть.

я пытался применить локальную оптимизацию для обработчиков прерываний таким образом:
Код
#pragma optimize=s 9
void timer0_irq_handler()
{  
  
  if(ii==1) {MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS;}
  MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60;
    
    crc = crc^regA;                                                               //подсчет контрольной суммы
    if(ii==2)                                                                         //вычисление бита паритета
    { if(crc == 0) regA = 0x0;
      else regA = 0x20000;
    }
    else
      {  
        if(datA&0x80000000) regA = 0x20000;
        else regA = 0x0;
      }
    regs->PIOA_ODSR = regA|front;      
    datA = datA<<1;
  ii--;                                                                                                  
  
  dummy = MipsTimerBase->TC_SR;
  
}

но напротив #pragma optimize=s 9 вылазит ворнинг следующего содержания: Warning[Go003]: Optimization can only be lowered from the default, not raised
Но ведь в настройках я вообще отключил оптимизацию. Почему возникает такое предупреждение?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 13:27
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 24 2009, 16:11) *
Но ведь в настройках я вообще отключил оптимизацию.

И зачем?

Цитата(Bulat @ Nov 24 2009, 16:11) *
я пытался применить локальную оптимизацию для обработчиков прерываний таким образом:

Верните глобальную оптимизацию на место и перепешите обработчики.

Где локальные переменные?
Зачем с периферией работать через левые указатели (regs, MipsTimerBase)?
Это вот -
Код
MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60;

- зачем повторять в каждом прерывании?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 23:57
Рейтинг@Mail.ru


Страница сгенерированна за 0.01496 секунд с 7
ELECTRONIX ©2004-2016