Код
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;
}
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 основных регистров процессора, чтобы обращаться напрямую к регистру и операции сдвига осуществлять с помощью одной строки асм-вставки? Как еще можно ускорить работу обработчика?
Заранее благодарен!