|
Приоритет и вложенность прерываний, матчасть |
|
|
|
Jun 5 2007, 03:16
|
Участник

Группа: Новичок
Сообщений: 18
Регистрация: 12-04-07
Пользователь №: 26 989

|
На сколько я понял, в 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
|
|
|
|
|
 |
Ответов
|
Jun 6 2007, 05:37
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата На сколько я понял с таким обработчиком, все команды (функции) тела прерывания будут использовать не IRQ стек, а общий стек лимитированный лишь размером памяти? Всё верно. Код ldr R14, =AT91C_BASE_AIC;Считать вектор в R0 ldr R0 , [R14, #AIC_IVR] ldr R14, =AT91C_BASE_AIC;Отметить окончание прерывания в str R14, [R14, #AIC_EOICR] Тут скорее всего косяк. Сбрасывать признак прерывания нужно в самом конце прерывания, а не сразу на входе. И общие прерывания уже должны быть запрещены. Вобщем алгоритм такой: 1. Прочитать вектор возникшего прерывания. 2. Перейти на обработчик 3. Сохранить адрес возврата (LR) и переключиться в SYS Mode 4. Разрешить общие прерывания 5. Обработать процедуру прерывания 6. Запретить общие прерывания 7. Переключиться обратно в IRQ Mode и восстановить LR 8. Сбросить флаг прерывания в AIC (AIC_EOICR) 9. Выйти из прерывания 7 и 8 можно поменять.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jun 6 2007, 10:53
|
Участник

Группа: Свой
Сообщений: 45
Регистрация: 19-04-07
Пользователь №: 27 172

|
Цитата(GetSmart @ Jun 6 2007, 11:37)  Код ldr R14, =AT91C_BASE_AIC;Отметить окончание прерывания в str R14, [R14, #AIC_EOICR] Тут скорее всего косяк. Сбрасывать признак прерывания нужно в самом конце прерывания, а не сразу на входе. И общие прерывания уже должны быть запрещены. Здесь нет косяка Общие прерывания запрещены строчкой выше (вот этой) Код msr CPSR_c, #I_BIT | ARM_MODE_IRQ;Запретить прерывания и переключиться назад в IRQ mode Запись в AT91C_BASE_AIC разрешает контроллеру прерываний SAM7 выставить новый запрос прерывания ядру. Ядро запустит обработчик только после выполнения последней команды обработчика, которая сделает возврат и переключит режим ядра из IRQ в USER/SUPERVISOR. Этот обработчик нормально работает в нескольких проектах с активным использованием прерываний
|
|
|
|
|
Jun 6 2007, 11:14
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Calculator @ Jun 6 2007, 16:53)  Здесь нет косяка Общие прерывания запрещены строчкой выше (вот этой) Код msr CPSR_c, #I_BIT | ARM_MODE_IRQ;Запретить прерывания и переключиться назад в IRQ mode Запись в AT91C_BASE_AIC разрешает контроллеру прерываний SAM7 выставить новый запрос прерывания ядру. Ядро запустит обработчик только после выполнения последней команды обработчика, которая сделает возврат и переключит режим ядра из IRQ в USER/SUPERVISOR. Этот обработчик нормально работает в нескольких проектах с активным использованием прерываний Запись -----//----- разрешает контроллеру прерываний реагировать (сразу исполнять, если разрешены общие прерывания) на прерывания с более низким приоритетом чем текущий. В прерываниях, в которых разрешены вложенные прерывания эту команду ставят в самом конце прерывания перед самым выходом, по вполне очевидным причинам. Запоминает же контроллер все прерывания, вне зависимости от их приоритета и записи в AT91C_BASE_AIC, что бы потом, после выхода из текущего прерывания (или даже внутри него) обработать все запомненные прерывания в порядке приоритета и пожеланий программиста. Цитата(maug @ Jun 6 2007, 16:47)  Эта фраза из документации на SAM7 с gaw.ru пункт 12.2.3 (Режимы работы ARM7TDMI) и
12.2.4.3 Типы исключительных ситуаций Ядро поддерживает пять типов исключительных ситуаций, работающих в привилегированном режиме. Ниже приведен их список: 1 быстрое прерывание (FIQ) 2 обычное прерывание (IRQ) 3 аварийная ситуация при работе с памятью (используется для реализации защищенного режима работы памяти или виртуальной памяти) 4 сбой при выполнении команды или выполнение несуществующей команды 5 программные прерывания (SWI) Я имел ввиду именно это. При возникновении исключительной ситуации используется персональный стек этого исключения. Прочитайте что ли файлик arm7tdmi.pdf А то придётся всё содержимое этого файла вам разжёвывать.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jun 8 2007, 06:22
|
Участник

Группа: Свой
Сообщений: 45
Регистрация: 19-04-07
Пользователь №: 27 172

|
Цитата(GetSmart @ Jun 6 2007, 17:14)  Запись -----//----- разрешает контроллеру прерываний реагировать (сразу исполнять, если разрешены общие прерывания) на прерывания с более низким приоритетом чем текущий. В прерываниях, в которых разрешены вложенные прерывания эту команду ставят в самом конце прерывания перед самым выходом, по вполне очевидным причинам. Могу повторить только то, что уже писал. Запись -----//----- действительно разрешает контроллеру прерываний реагировать, но не исполнять, т.к. сброшен флаг разрешения прерываний IRQ в регистре статуса. Последняя команда обработчика прерывания переключает режим ядра, делает возврат в фоновую програму и разрешает прерывания IRQ. Если они есть, то самое приоритетное из них будет выполнено после выполнения одной инструкции из фоновой программы Цитата(maug @ Jun 5 2007, 17:45) Этот код видел вот только из за особенности ICCARM асемблера не могу прикрутить аналогичную. не понимает команды работы ldr R14, =AT91C_BASE_AIC ;Считать вектор в R0 ldr R0 , [R14, #AIC_IVR] ldr R14, =AT91C_BASE_AIC ;Отметить окончание прерывания в str R14, [R14, #AIC_EOICR]
Может у кого нибудь есть опыт работы ICC?
На сколько я понял с таким обработчиком, все команды (функции) тела прерывания будут использовать не IRQ стек, а общий стек лимитированный лишь размером памяти? Опыта работы с ICC у меня нет, но нужно просто разобраться, почему не понимаются эти команды. Может быть у ассемблера немного отличается синтаксис, может быть нет define на AT91C_BASE_AIC, может быть define есть, но равен не тому же, чему в IAR. На всякий случай вот эти define: Код AT91C_BASE_AIC EQU 0xFFFFF000 ;Базовый адрес контроллера прерываний AIC_IVR EQU 0x100;Регистр вектора IRQ (смещение) AIC_FVR EQU 0x104;Регистр вектора FIQ AIC_EOICR EQU 0x130;Регистр "Окончание прерывания" Стек режима IRQ использоваться будет, но мало и его максимальная длина фиксирована. Для максимум 8 вложенных прерываний (а больше не разрешит контроллер прерываний) длина стека IRQ должна быть 3*4*8 байт (3 двойных слова на 8 уровней приоритетов). Если используется всего пара приоритетов, то соответственно 3*4*2
Сообщение отредактировал Calculator - Jun 8 2007, 06:27
|
|
|
|
Сообщений в этой теме
maug Приоритет и вложенность прерываний Jun 5 2007, 03:16 Calculator Может размер стека режима прерываний мал? В станда... Jun 5 2007, 05:46 GetSmart Есть такая штука как вложенные прерывания. Так вот... Jun 5 2007, 06:30 maug ЦитатаМожет размер стека режима прерываний мал? В ... Jun 5 2007, 06:46 Calculator Цитата(GetSmart @ Jun 5 2007, 12:30) Кста... Jun 5 2007, 10:49 maug Нашел вставки в прерывания аналог слово __nested.
... Jun 5 2007, 07:59 GetSmart Похоже на правду.
А в каком компиляторе пишите на... Jun 5 2007, 10:45 GetSmart Цитата(Calculator)В SAM7 можно, его контроллер пре... Jun 5 2007, 11:26 maug Цитата(GetSmart @ Jun 5 2007, 17:45) А в ... Jun 6 2007, 02:45 zltigo Цитата(maug @ Jun 6 2007, 05:45) На сколь... Jun 6 2007, 07:02 GetSmart zltigo, не мутите воду. Запутаете всех окончательн... Jun 6 2007, 07:07 zltigo Цитата(GetSmart @ Jun 6 2007, 10:07) Запу... Jun 6 2007, 08:11  maug Эту тему я открыл, чтобы разобраться окончательно ... Jun 6 2007, 09:49 GetSmart 1. System обычно. Иногда User.
2. Вообще непонятно... Jun 6 2007, 10:33 maug Цитата(GetSmart @ Jun 6 2007, 17:33) 2. В... Jun 6 2007, 10:47 telerobot Здравствуйте.
У меня вопрос. Я работаю с AT91SAM7X... Apr 10 2010, 18:49 malysh_nrg Цитата(telerobot @ Apr 10 2010, 23:04) чт... Apr 12 2010, 11:36 sergeeff Цитата(telerobot @ Apr 10 2010, 23:04) Об... Apr 12 2010, 15:20 sergeeff Посмотреть свежий топик http://electronix.ru/forum... Apr 10 2010, 23:47
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|