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

 
 
> вопрос по работе с тремя прерываниями одинакового приоритета,, которые могут возникнуть одновременно. 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
2 страниц V  < 1 2  
Start new topic
Ответов (15 - 20)
Bulat
сообщение Nov 24 2009, 14:00
Сообщение #16


Местный
***

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



Цитата(aaarrr @ Nov 24 2009, 18:27) *
И зачем?


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

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

- зачем повторять в каждом прерывании?

-Когда я глобальную оптимизацию включаю, у меня работать перестает) ну не конкретно эти обработчики, а что-то другое.
-Если использовать локальные переменные внутриобработчика, тогда всеравно их значения нужно передавать через функцию основной программе (ii-счетчик, datA-сдвиговый буфер).
-А как лучше обращаться к регистрам таймера из обработчика прерывания?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 24 2009, 15:02
Сообщение #17


Гуру
******

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



Цитата(Bulat @ Nov 24 2009, 17:00) *
-Когда я глобальную оптимизацию включаю, у меня работать перестает) ну не конкретно эти обработчики, а что-то другое.

Вот с исправления этой проблемы и надо начинать. Все остальное пока забудьте.

Цитата(Bulat @ Nov 24 2009, 17:00) *
-Если использовать локальные переменные внутриобработчика, тогда всеравно их значения нужно передавать через функцию основной программе (ii-счетчик, datA-сдвиговый буфер).

regA, dummy

Цитата(Bulat @ Nov 24 2009, 17:00) *
-А как лучше обращаться к регистрам таймера из обработчика прерывания?

А зачем это делать вообще? Во-первых, зачем нужно использовать все три регистра (RA-RC)? Во-вторых, откуда следует необходимость их перезаписи?
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 25 2009, 12:02
Сообщение #18


Местный
***

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



Цитата(aaarrr @ Nov 24 2009, 20:02) *
Вот с исправления этой проблемы и надо начинать. Все остальное пока забудьте.


regA, dummy


А зачем это делать вообще? Во-первых, зачем нужно использовать все три регистра (RA-RC)? Во-вторых, откуда следует необходимость их перезаписи?


Во-первых, я настраиваю таймер в соответствии с документацией. Таймер работает в таком режиме, что при равенстве RA бит сигнал устанавливается в 1, а при равенстве RC сбрасывается, при этом RB=RC.

Во-вторых, мне необходимо генерировать 32-битную последовательность импульсов с частотой 100кГц и с паузой между 32-битными словами 40мкс, то есть 4Т. Генерацию импульсов и паузу я осуществляю с помощью одного таймера, благодаря изменению регистров RA-RC в процессе его работы.

Ниже в комментариях к коду я объясняю работу:
Код
//обработчик прерываний таймера, который осуществляет подготовку каждого бита передаваемого слова
void timer0_irq_handler()
{
unsigned int regA;
  int dummy;
  int  crc;
  
  if(ii==1) {MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS;}      //останов таймера после передачи всего слова
  MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60;//настройка таймера на частоту передачи 100кГц
    
    crc = crc^regs->PIOA_ODSR;                                                  //подсчет контрольной суммы
    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;                                                  //Смещение буфера с передаваемым 32-битным словом
  ii--;                                                                         //счетчик переданных бит
  dummy = MipsTimerBase->TC_SR;
}

//Функция подготавливающая 32-битные слова для передачи и запускающая таймер
void Write_TRA()
{
  unsigned int regA;  
//подготовка слова datA для последовательной передачи
  
  //Вывод первого бита в порт, чтобы при возникновении прерывания он сразу был передан
  if(datA&0x80000000) regA = 0x20000;
  else regA = 0x0;
  regs->PIOA_ODSR = regA|front;
  datA = datA<<1; //сдвигаем слово

  ii=32;   //загружаем счетчик передаваемых слов
  //запускаем таймер  
  MipsTimerBase->TC_CCR = AT91C_TC_CLKEN;                                    
  MipsTimerBase->TC_CCR = AT91C_TC_SWTRG;  

  while(ii!=0);  //ожидаем, пока передадуться все 32 бита
  
  //устанавливаем значения регистров таким образом, чтобы он начал работать с паузы 40мкс (чтобы выдержать необходимую по протоколу паузу), а затем был короткий импульс 5мкс, по которому ужебудет передаваться первый бит нового слова.  
  MipsTimerBase->TC_RA = 178; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 200;
    
}


поэтому я вынужден уже в обработчике прерывания устанавливать новые значения регистров, соответствующие 100кГц, чтобы оставшиеся 31 бит передавать с этой частотой.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 25 2009, 12:12
Сообщение #19


Гуру
******

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



Цитата(Bulat @ Nov 25 2009, 15:02) *
Таймер работает в таком режиме, что при равенстве RA бит сигнал устанавливается в 1, а при равенстве RC сбрасывается, при этом RB=RC.

И что получается - тактовый сигнал? Тогда зачем городить синхронный последовательный интерфейс программно, когда есть SPI и SSC?
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 25 2009, 12:45
Сообщение #20


Местный
***

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



Цитата(aaarrr @ Nov 25 2009, 17:12) *
И что получается - тактовый сигнал? Тогда зачем городить синхронный последовательный интерфейс программно, когда есть SPI и SSC?

потому что мне нужно передавать 32 битный код и еще параллельно получать от контроллера тактовую частоту на выходе, особенность протокола и аппаратной реализации.
При средней глобальной оптимизации мне удалось добиться стабильной, одновременной передачи и приема данных, но при передачи периодически проскакивают ошибочные слова, но посли оптимизации их стало значительно меньше. Когда я включаю максимальную оптимизацию по скорости, то передача не работает, только прием. Судя по всему оптимизатор что-то делает с MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60; в обработчике, так как эта операция повторяется при каждом прерывании.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 25 2009, 14:08
Сообщение #21


Гуру
******

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



Цитата(Bulat @ Nov 25 2009, 15:45) *
потому что мне нужно передавать 32 битный код и еще параллельно получать от контроллера тактовую частоту на выходе, особенность протокола и аппаратной реализации.

Это можно сделать при помощи SSC.

Цитата(Bulat @ Nov 25 2009, 15:45) *
Судя по всему оптимизатор что-то делает с 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 Текстовая версия Сейчас: 6th September 2025 - 12:45
Рейтинг@Mail.ru


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