Перейти к содержанию
    

Помогите разобраться, что не так. Хочу разобраться с прерываниями по изменению уровня на PIOA, прерывание должно наступать по нажатию джойстика. Код брал из примера,немного переработав для удобства. Не входит в прерывание и все тут.

 

 

void main (void)
{
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK );
AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK );
AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SW3_MASK | SW4_MASK); 


AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA, PIO_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);
//* set the interrupt by software
AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);

for (;;)
{}
}


// обработчик

void pio_c_irq_handler ( void )
{
int dummy;
count_int_pio++;

    
    AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000); 
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
  
    dummy =AT91C_BASE_PIOA->PIO_ISR;
    


}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

// обработчик

Это не весь обработчик. Показывайте, что сидит на векторе исключения, как осуществляется переход по адрусу из контроллера прерываний. Используете ли отладчик? Если да - не открыто ли окно с регистрами контроллера прерываний?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно просмотреть ассемблерный обработчик, начиная с IRQ_Handler_Entry;

внешние резисторные подтяжки могут оказаться не лишними;

AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE (по причинам, до конца мне не ясным:));

+ сбрасывать флаги прерываний в периферии и AIC надежней вручную;

 

кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт;

компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации"

Изменено пользователем VSt&

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE (по причинам, до конца мне не ясным:));

Дык Вы бы уяснили для себя причины, прежде чем советы давать. Работать по фронту с внутренними источниками весьма черевато.

 

кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт;

компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации"

Не может, ибо это volatile. Но можно просто написать AT91C_BASE_PIOA->PIO_ISR, без всяких dummy.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не сердитесь, если что не так, я хочу разобраться.

 

Использую JTAG SAM-ICE Segger + кит на AT91SAM7A3 + IAR 4.42A .

Окно с регистрами контроллера прерываний было, открыто,закрыл, все равно...

Флаги прерываний AIC и PIO сбросил вручную. менял AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL

на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE . Все тоже.

 

Объясните,пожалуйста,как все это происходит

 

 

Я не назначаю вручную адресс обработчика прерывания.Я так понимаю это должно делаеться автоматически. При возникновении прерывания от PIO,если оно разрешено, автоматом читается вектор

прерывания AIC_IVR и возвращается значение адресса обработчика соответсвующего прерывания,

который должен сидеть AIC_SVR[AT91C_ID_PIOA] для прерывания от PIO.

 

А как посмтотреть что сидит на векторе исключения,

как осуществляется переход по адрессу из контроллера прерываний?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вот. Зная компилятор можно продолжать.

Использую JTAG SAM-ICE Segger + кит на AT91SAM7A3 + IAR 4.42A .
Тогда откройте окно дизассемблера и посмотрите на адрес 0x18. Там будет или что-то вроде LDR PC,[PC, #24] и тогда по адресу 0x38 будет лежать адрес обработчика, либо там будет LDR PC, [PC, #-3872] - тогда это как раз и есть чтение AIC_IVR и передача управления.

В певом случае вам надо в окне дизассемблера пролистать до адреса обработчика и посмотреть, что там находится. Если там заглушка типа "переход на себя", надо добавить в программу обработчик:

#pragma vector = 0x18
__irq __arm void IRQ_Switch() {
    void (*Handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    Handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic
}

Во втором случае надо ваш обработчик объявить как __irq __arm void pio_c_irq_handler ( void ) и добавить в его конце AT91C_BASE_AIC->AIC_EOICR = 0;

 

В любом случае полезно добавить в программу после настройки контроллера строчку AT91C_BASE_AIC->AIC_EOICR = 0; ибо если вы находясь в обработчике прерывания нажмете иконку сброса в отладчике, сброса контроллера прерываний не происходит и прерывания с таким и более низким приоритетом останутся запрещены.

И самое главное - я не вижу в вашей программе строчки __enable_interrupt();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по Адрессу

irgvec :

0x18 содержится IRQ_Handler_Entry ; IRQ 0x90

 

по

IRQ_Handler_Entry:

0x90 SUB LR,LR, #0x4

 

 

Это наверное и есть обработчик,

А почему нет разрешения прерываний, ведь

 

// настроили прерывания,указали обработчик

AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);

 

// разрешили прерывания от маски SW4_MASK PIOA

AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);

 

// разрешили прерывания для контроллера прерываний от периферии AT91C_ID_PIOA

AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по

IRQ_Handler_Entry:

0x90 SUB LR,LR, #0x4

Это наверное и есть обработчик,

А дальше что (по коду)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему нет разрешения прерываний, ведь
А кто будет сбрасывать бит I в CPSR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подключил <intrinsics.h> и вставил

функцию __enable_interrupt().

 

 

Вот текст программы

void pio_c_irq_handler ( void )
{
int dummy;

   

    count_int_pio++;

    
    
    AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000); 
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
  
    dummy =AT91C_BASE_PIOA->PIO_ISR;
    dummy=AT91C_BASE_AIC->AIC_ISR;
    dummy=AT91C_BASE_AIC->AIC_IECR;  

}




void main( void )

{


       AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
        
       AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK );
       AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK );

    

       AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SW4_MASK); 
     
       AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL,            AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);
    
        AT91C_BASE_AIC->AIC_EOICR = 0; 
        
        __enable_interrupt();
        
        AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);
    
       AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);  
       


for (;;)
    {

    }


}

 

Вот, то что в окне дизасемблерра

IRQ_Handler_Entry:
  00000090  E24EE004  SUB          LR, LR, #0x4
  00000094  E92D4000  STMDB        SP!, {LR}
  00000098  E14FE000  MRS          LR, SPSR
  0000009C  E92D4000  STMDB        SP!, {LR}
  000000A0  E92D0001  STMDB        SP!, {R0}
  000000A4  E59FE048  LDR          LR, [PC, #+72]          ; [_?2 (0xF4)] =AIC_SMR (0xFFFFF000)
  000000A8  E59E0100  LDR          R0, [LR, #+256]
  000000AC  E58EE100  STR          LR, [LR, #+256]
  000000B0  E321F013  MSR          CPSR_c, #0x13
  000000B4  E92D500E  STMDB        SP!, {R1,R2,R3,R12,LR}
  000000B8  E1A0E00F  MOV          LR, PC
  000000BC  E12FFF10  BX           R0
  000000C0  E8BD500E  LDMIA        SP!, {R1,R2,R3,R12,LR}
  000000C4  E321F092  MSR          CPSR_c, #0x92
  000000C8  E59FE024  LDR          LR, [PC, #+36]          ; [_?2 (0xF4)] =AIC_SMR (0xFFFFF000)
  000000CC  E58EE130  STR          LR, [LR, #+304]
  000000D0  E8BD0001  LDMIA        SP!, {R0}
  000000D4  E8BD4000  LDMIA        SP!, {LR}
  000000D8  E16FF00E  MSR          SPSR_cxsf, LR
  000000DC  E8FD8000  LDMIA        SP!, {PC}^
AT91F_Default_FIQ_handler:
  000000E0  EAFFFFFE  B            AT91F_Default_FIQ_handler; 0xE0
AT91F_Default_IRQ_handler:
  000000E4  EAFFFFFE  B            AT91F_Default_IRQ_handler; 0xE4

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подключил <intrinsics.h> и вставил

функцию __enable_interrupt().

Хорошо. Пойдем от самого простого. Поставьте точку останова на адрес 0x18. Вы попадете на эту точку останова?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При том же исходном тесте , если комментирую в основном тексте программы,после настройки контроллера прерываний строчку AT91C_BASE_AIC->AIC_EOICR = 0 , то в точку останова не попадаю.

 

 

Если оставляю AT91C_BASE_AIC->AIC_EOICR = 0 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика.

Ставлю точку на адрес 0x18, попадаю туда, далее пошагово попадаю на IRQ_Handler_Entry, а с нее попадаю на pio_c_irq_handler, далее по коду дохожу до "вечного цикла", причем джойстик я не трогаю, т.е. прервание не инициализирую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При том же исходном тесте , если комментирую в основном тексте программы,после настройки контроллера прерываний строчку AT91C_BASE_AIC->AIC_EOICR = 0 , то в точку останова не попадаю.
Почему это происходит я писал в конце сообщения #6.
Если оставляю AT91C_BASE_AIC->AIC_EOICR = 0 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика.
Простите, а какой уровень приходит на входы порта от джойстика в состоянии покоя?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В состоянии покоя на входах джойстика уровни "1" , но эти уровни от встроенных Pull-up резисторов в котроллер.

 

При нажатии на джойстик происходит замыкание входа на "землю".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В состоянии покоя на входах джойстика уровни "1" , но эти уровни от встроенных Pull-up резисторов в котроллер.
А какого поведения вы ожидаете от контроллера после AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...