Из работающего атмеловского примера выделил код настройки AIC и PIT для организации работы по прерываниям.
Собственно ниже то что получилось.
CODE
void IRQ_ConfigureIT(unsigned int source, unsigned int mode, void( *handler )( void ))
{
// Disable the interrupt first
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
// Configure mode and handler
AT91C_BASE_AIC->AIC_SMR[source] = mode;
AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;
// Clear interrupt
AT91C_BASE_AIC->AIC_ICCR = 1 << source;
}
//------------------------------------------------------------------------------
/// Enables interrupts coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void IRQ_EnableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IECR = 1 << source;
}
//------------------------------------------------------------------------------
/// Disables interrupts coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void IRQ_DisableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
}
//------------------------------------------------------------------------------
void PIT_Init(unsigned int period, unsigned int pit_frequency)
{
AT91C_BASE_PITC->PITC_PIMR = period? (period * pit_frequency + 8) >> 4 : 0;
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//------------------------------------------------------------------------------
/// Set the Periodic Interval Value of the PIT.
/// \param piv PIV value to set.
//------------------------------------------------------------------------------
void PIT_SetPIV(unsigned int piv)
{
AT91C_BASE_PITC->PITC_PIMR = (AT91C_BASE_PITC->PITC_PIMR & AT91C_PITC_PIV)
| piv;
}
//------------------------------------------------------------------------------
/// Enables the PIT if this is not already the case.
//------------------------------------------------------------------------------
void PIT_Enable(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//----------------------------------------------------------------------------
/// Enable the PIT periodic interrupt.
//----------------------------------------------------------------------------
void PIT_EnableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Disables the PIT periodic interrupt.
//------------------------------------------------------------------------------
void PIT_DisableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT mode register.
/// \return PIT_MR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetMode(void)
{
return AT91C_BASE_PITC->PITC_PIMR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT status register, clearing it as a side effect.
/// \return PIT_SR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetStatus(void)
{
return AT91C_BASE_PITC->PITC_PISR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT Image Register, to read PICNT and CPIV without
/// clearing the current values.
/// \return PIT_PIIR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetPIIR(void)
{
return AT91C_BASE_PITC->PITC_PIIR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT Value Register, clearing it as a side effect.
/// \return PIT_PIVR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetPIVR(void)
{
return AT91C_BASE_PITC->PITC_PIVR;
}
//------------------------------------------------------------------------------
/// Handler for PIT interrupt. Increments the timestamp counter.
//------------------------------------------------------------------------------
void ISR_Pit(void)
{
unsigned int status;
// Read the PIT status register
status = PIT_GetStatus() & AT91C_PITC_PITS;
if (status != 0) {
// 1 = The Periodic Interval timer has reached PIV since the last read of PIT_PIVR.
// Read the PIVR to acknowledge interrupt and get number of ticks
//Returns the number of occurrences of periodic intervals since the last read of PIT_PIVR.
timestamp += (PIT_GetPIVR() >> 20);
}
}
//------------------------------------------------------------------------------
/// Configure the periodic interval timer (PIT) to generate an interrupt every
/// millisecond.
//------------------------------------------------------------------------------
void ConfigurePit(void)
{
// Initialize the PIT to the desired frequency
PIT_Init(PIT_PERIOD, BOARD_MCK / 1000000);
// Configure interrupt on PIT
IRQ_DisableIT(AT91C_ID_SYS);
IRQ_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, ISR_Pit);
IRQ_EnableIT(AT91C_ID_SYS);
PIT_EnableIT();
// Enable the pit
PIT_Enable();
}
void main(void)
{
//разрешение тактирования pio
AT91C_BASE_PMC->PMC_PCER = (1ul<<AT91C_ID_PIOA)|(1ul<<AT91C_ID_SYS)|(1ul<<AT91C_ID_FIQ);
//попытка настройки gpio
AT91C_BASE_PIOA->PIO_OER = (1ul<<3)|(1ul<<2)|(1ul<<1)|(1ul<<0);
AT91C_BASE_PIOA->PIO_SODR = (1ul<<3)|(1ul<<2)|(1ul<<1)|(1ul<<0);
//настройка PIT, 1mС, установлено прерывание
ConfigurePit();
long status=0;
for(;;)
{
static long timer=1000000;
if(timer > 0) timer--;
else
{
timer=1000000;
if(status == 0)
{
//устанавливаем ножку
AT91C_BASE_PIOA->PIO_SODR = (1ul<<3)|(1ul<<2)|(1ul<<1)|(1ul<<0);
status = 1;
}
else
{
//сбрасываем ножку
AT91C_BASE_PIOA->PIO_CODR = (1ul<<3)|(1ul<<2)|(1ul<<1)|(1ul<<0);
status = 0;
}
}
}
Код в основном цикле использую для того чтобы убедится что процессор работает. Точнее он работает если в ConfigurePIT() закоментировать разрешение прерывания PIT PIT_EnableIT(). Отличие моего проекта от атмеловского в том что я пытаюсь настроить только одно прерывание а там учавствуют несколько (от таймера, PIO).
Думал что проблема могла быть в том что не подключил тактирование AIC. На всякий случай ввёл
Код
AT91C_BASE_PMC->PMC_PCER = (1ul<<AT91C_ID_PIOA)|(1ul<<AT91C_ID_SYS)|(1ul<<AT91C_ID_FIQ);
Не помогло. Вероятно я чтото упускаю в коде или настройках.
P.S. Вопрос на засыпку - у меня тактовая частота процессора 48MHz (планируется использование USB). И при этом исполняю код только из flash. Не слишком ли это высокая частота?