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

 
 
> Как можно быстро обращаться к регистрам таймера из прерывания?, at91sam7s
Bulat
сообщение Dec 3 2009, 16:04
Сообщение #1


Местный
***

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



По прерыванию от порта данные записываются в сдвиговый регистр. Прерывания возможны от 4 различных выводов во всевозможных комбинациях. Обработчик помимо записи в сдвиговый буфер и сдвига должен каждый раз запускать таймер, который контролирует паузу между битами поступаемыми на порт контроллера. Ниже приведен код:
Код
const AT91PS_TC    PauseTimerBase1 =AT91C_BASE_TC1;
const AT91S_PAUSE_TIMER1 PauseTimer1 = { AT91C_ID_TC1,0,240,480,960,1920,3840,TC_CLKS_MCK8};

const AT91PS_TC    PauseTimerBase2 =AT91C_BASE_TC2;
const AT91S_PAUSE_TIMER2 PauseTimer2 = { AT91C_ID_TC2,0,240,480,960,1920,3840,TC_CLKS_MCK8};

__ramfunc void irq_Receive()
{  
  unsigned int dummy;
  unsigned int source;                                                          //источник прерываний
  
  source = regs->PIOA_PDSR&0x780;                                               //определяем источник прерываний
  
    
    if(source==0x200) {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA|0x80000000;} //A1

    if(source==0x400) {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA&0x7FFFFFFF;}  //B1
  
    if(source==0x80)  {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB|0x80000000;} //A2

    if(source==0x100) {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB&0x7FFFFFFF;}  //B2
  
    if(source==0x280) {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB|0x80000000;} //A1,A2

    if(source==0x500) {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA&0x7FFFFFFF; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB&0x7FFFFFFF;}  //B1,B2
  
    if(source==0x300) {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB&0x7FFFFFFF;} //A1,B2

    if(source==0x480) {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1;  i_shB++; recB = recB|0x80000000; PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1;  i_shA++; recA = recA&0x7FFFFFFF;}  //A2,B1
  
  
  dummy = AT91C_BASE_PIOA->PIO_ISR;
    
}

То есть, в обработчике учитываются 8 различных комбинаций, которые могут возникнуть на выводах порта с учетом маски. В каждом случае необходимо запускать и сбрасывать таймер паузы или же 2 таймера паузы для 1 и 2 каналов, в зависимости от комбинации на порту контроллера. Если данные на порт контроллера перестанут поступать, сработает таймер паузы и данные recA и recB перепишутся в буфер. Код работает, но недостаточно быстро. Контроллер не успевает принять все данные. Данные поступают в виде 32-битных слов со скоростью 100кГц, пауза между словами 40мкс.
Можно ли как то оптимизировать этот обработчик (оптимизатор IAR включен на максимум по скорости, inline threshold=16)? Есть ли возможность обращаться к регистрам таймера напрямую? Можно ли в качестве сдвигового регистра (recA,recB) назначить один из 15 основных регистров процессора, чтобы обращаться напрямую к регистру и операции сдвига осуществлять с помощью одной строки асм-вставки? Как еще можно ускорить работу обработчика?
Заранее благодарен!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
baralgin
сообщение Dec 3 2009, 16:46
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680



Эээ.. Тут вроде явно напрашивается switch вместо 8 if'ов. Не понятно что такое recA и recB. Если вы хотите чтобы компилятор их размещал в регистрах, то скопируйте их в локальные переменные, обработайте и потом отгружайте уже готовые значения обратно. Если они не volatile , то компилятор сам это будет делать.

Цитата
Как еще можно ускорить работу обработчика?
Писать правильный код на Си smile.gif .
Go to the top of the page
 
+Quote Post
Bulat
сообщение Dec 4 2009, 04:37
Сообщение #3


Местный
***

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



Цитата(baralgin @ Dec 3 2009, 21:46) *
Эээ.. Тут вроде явно напрашивается switch вместо 8 if'ов.

А switch быстрее if?
Причина редактирования: Излишнее цитирование.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 11:30
Рейтинг@Mail.ru


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