На сколько я понял, в SAM7 уровень прерываний заложен, но чтобы он правильно работал, необходимо написать правильный обработчик прерывания. Или я не прав? В простейшем случае необходимо в начале и в конце обработчика поставить define библиотеки ...:
__ENABLE_INTERRUPT();
__DISABLE_INTERRUPT();
Провел несколько простых экспериментов, с использованием таймеров 0 и 1
Код
#define TIMER0_INTERRUPT_LEVEL 0
#define TIMER1_INTERRUPT_LEVEL 1
#pragma interrupt_handler Timer0_CIrqHandler
void Timer0_CIrqHandler(void)
{
unsigned int status,r0;
__ENABLE_INTERRUPT();
status = TC0_SR; // Read timer status register to clear interrupt
PIO_CODR = (1<<0); // LED1 ON
for(r0=0; r0<0x5FFF; r0++);
PIO_SODR = (1<<0); // LED1 OFF
AIC_EOICR = status;
__DISABLE_INTERRUPT();
}
#pragma interrupt_handler Timer1_CIrqHandler
void Timer1_CIrqHandler(void)
{
unsigned int status,r1;
__ENABLE_INTERRUPT();
status = TC1_SR; // Read timer status register to clear interrupt
PIO_CODR = (1<<1); // LED2 ON
for(r1=0; r1<0x4FF; r1++);
PIO_SODR = (1<<1); // LED2 OFF
AIC_EOICR = status;
__DISABLE_INTERRUPT();
}
void timer0_init ( void )
{
PMC_PCER = (0x1 << AT91C_ID_TC0);
TC0_CCR = AT91C_TC_CLKDIS;
TC0_IDR = 0xFFFFFFFF;
AIC_SVR12 = (unsigned int) Timer0_CIrqHandler;
AIC_SMR12 =AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE|TIMER0_INTERRUPT_LEVEL;
AIC_IECR = (0x1 << AT91C_ID_TC0);
TC0_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_CPCTRG;
TC0_RC = 0x0FF0;
TC0_IER = AT91C_TC_CPCS;
TC0_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
}
void timer1_init ( void )
{
PMC_PCER = (0x1 << AT91C_ID_TC1);
TC1_CCR = AT91C_TC_CLKDIS;
TC1_IDR = 0xFFFFFFFF;
AIC_SVR13 = (unsigned int) Timer1_CIrqHandler;
AIC_SMR13 =AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE|TIMER1_INTERRUPT_LEVEL;
AIC_IECR = (0x1 << AT91C_ID_TC1);
TC1_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_CPCTRG;
TC1_RC = 0x00FF;
TC1_IER = AT91C_TC_CPCS;
TC1_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
}
после использования __ENABLE_INTERRUPT(); __DISABLE_INTERRUPT();
действительно уровень прерывания стал работать как надо.
Но вот попробовал подключить ШИМ:
Код
#define F_PWC 0xFF
#define PWMC_INTERRUPT_LEVEL 5
#pragma interrupt_handler PWMC_CIrqHandler
void PWMC_CIrqHandler(void)
{
unsigned int status,rir,ss;
__ENABLE_INTERRUPT();
status = PWM_ISR;
AIC_ICCR = (0x1 << AT91C_ID_PWMC);
PWM_CMR0 = (0<<10)|0x03;
PWM_CUPD0 = F_PWC/3;
AIC_EOICR = status;
__DISABLE_INTERRUPT();
}
void init_pwm(){
int i;
*AT91C_PIOA_PDR = (1<<23); // подключаем выв PA23 к шиму
*AT91C_PIOA_BSR = (1<<23);
PMC_PCER = (1<<AT91C_ID_PWMC);
AIC_SMR10 = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | PWMC_INTERRUPT_LEVEL;
AIC_SVR10 = (unsigned int) PWMC_CIrqHandler;
AIC_IECR = (1 << AT91C_ID_PWMC);
// PWM_MR =(0x00<<24)|(0x01<<16)|(0x00<<8) |(0x01<<0);
PWM_CMR0 = (0<<10)| (0<<9)| (0<<8) | 0x03;
PWM_CPRD0 = F_PWC;
PWM_CDTY0 = F_PWC/10;
PWM_IER = AT91C_PWMC_CHID0;
PWM_ENA = AT91C_PWMC_CHID0;
}
}
В таком виде программа виснет, как только срабатывает прерывание ШИМа, точнее когда оно выходит из него.
Пробовал убрать __ENABLE_INTERRUPT(); __DISABLE_INTERRUPT(); из всех прерываний все работает, только без преоритетов. По отдельности так же все работает. В чем дело не пойму. Может необходимо более полный обработчик написать? помогите!
Пишу на ICCARM для AT91SAM7S256. Startup стандартный crtat91sam7s.s
Сообщение отредактировал maug - Jun 5 2007, 03:20