реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Приоритет и вложенность прерываний, матчасть
maug
сообщение Jun 5 2007, 03:16
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 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
Go to the top of the page
 
+Quote Post
Calculator
сообщение Jun 5 2007, 05:46
Сообщение #2


Участник
*

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



Может размер стека режима прерываний мал? В стандартных стартап-файлах и в примерах на это внимание не обращают.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 5 2007, 06:30
Сообщение #3


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Есть такая штука как вложенные прерывания. Так вот. Чтобы их разрешить в АРМе нужно кое-что особенное. Вобщем пролог и эпилог таких прерываний отличается от обычных. Кстати, в обычных прерываниях нельзя разрешать прерывания. По крац\йней мере в ИАРе так. Для вложенных прерываний существует слово __nested. К примеру так описывается заголвок прерывания:
__irq __arm __nested Timer0Interrupt()


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
maug
сообщение Jun 5 2007, 06:46
Сообщение #4


Участник
*

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



Цитата
Может размер стека режима прерываний мал? В стандартных стартап-файлах и в примерах на это внимание не обращают

Размер стека IRQ сделал 1000 вроде для такой программы это с N кратным запасом

Цитата
Есть такая штука как вложенные прерывания. Так вот. Чтобы их разрешить в АРМе нужно кое-что особенное. Вобщем пролог и эпилог таких прерываний отличается от обычных. Кстати, в обычных прерываниях нельзя разрешать прерывания. По крац\йней мере в ИАРе так. Для вложенных прерываний существует слово __nested. К примеру так описывается заголвок прерывания:
__irq __arm __nested Timer0Interrupt()

Я примерно об этом и имел ввиду, говоря об специальном обработчике прерывания. Примерно то и суть действий ясна, да вот только примерно. Может кто знает как правильно написать обработчик прерывания или хотябы где посмотреть?
Go to the top of the page
 
+Quote Post
maug
сообщение Jun 5 2007, 07:59
Сообщение #5


Участник
*

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



Нашел вставки в прерывания аналог слово __nested.
#define IENABLE /* Nested Interrupts Entry */
asm(" MRS LR, SPSR"); /* Copy SPSR_irq to LR */
asm (" STMFD SP!, {LR}"); /* Save SPSR_irq */
asm (" MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode)

#define IDISABLE /* Nested Interrupts Exit */
asm (" LDMFD SP!, {LR}"); /* Restore LR */
asm (" MSR CPSR_c, #0x92"); /* Disable IRQ (IRQ Mode) */
asm (" LDMFD SP!, {LR}"); /* Restore SPSR_irq to LR */
asm (" MSR SPSR_cxsf, LR"); /* Copy LR to SPSR_irq */

Вроде все стало работать.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 5 2007, 10:45
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Похоже на правду.

А в каком компиляторе пишите на си?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Calculator
сообщение Jun 5 2007, 10:49
Сообщение #7


Участник
*

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



Цитата(GetSmart @ Jun 5 2007, 12:30) *
Кстати, в обычных прерываниях нельзя разрешать прерывания. По крайней мере в ИАРе так

В SAM7 можно, его контроллер прерываний обеспечивает при разрешенных прерываниях обработку только более приоритетных прерываний, чем выполняемое в данный момент. Правда есть нюанс, связанный с армовской архитектурой. Прерывание переключает режим ядра в IRQ. Для того, чтобы не испортить адрес возврата и флаги, сначала нужно сохранить их в стеке IRQ, а затем переключиться в режим USER или SUPERVISOR, и только после этого разрешить прерывания.
Обработчик IRQ из IAR'овского cstartup для SAM7 отличается от обработчиков для других ARMов.
Код
IRQ_Handler_Entry:
        sub     LR, LR, #4               ;Сохранение LR_irq в стеке IRQ
        stmfd   SP!, {LR}
        mrs     R14, SPSR                ;Сохранить SPSR в стеке для вложенных прерываний
        stmfd   SP!, {R14}
        stmfd   SP!, {R0}                ;Сохранение R0 в стеке IRQ

        ldr     R14, =AT91C_BASE_AIC     ;Считать вектор в R0
        ldr     R0 , [R14, #AIC_IVR]
        msr     CPSR_c, #ARM_MODE_SVC    ;Разрешить прерывания и переключиться в Supervisor Mode
        stmfd   SP!, {R1-R3, R12, R14}   ;Сохранить используемые регистры в User-стеке

        mov     LR, PC                   ;Выполнить процедуру прерывания по вектору из AIC_IVR
        bx      R0

        ldmia   SP!, { R1-R3, R12, R14}  ;Восстановить используемые регистры из User-стека
        msr     CPSR_c, #I_BIT | ARM_MODE_IRQ;Запретить прерывания и переключиться назад в IRQ mode

        ldr     R14, =AT91C_BASE_AIC     ;Отметить окончание прерывания в регистре AIC_EOICR
        str     R14, [R14, #AIC_EOICR]

        ldmia   SP!, {R0}                ;Восстановление SPSR_irq и R0 из стека IRQ
        ldmia   SP!, {R14}
        msr     SPSR_cxsf, R14
        ldmia   SP!, {PC}^               ;Восстановление скорректированного LR_irq из IRQ-стека прямо в PC

Сишные обработчики при этом оформляются не только без слова __nested, но и без interrupt_handler, то есть как обычные процедуры.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 5 2007, 11:26
Сообщение #8


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Calculator)
В SAM7 можно, его контроллер прерываний обеспечивает при разрешенных прерываниях обработку только более приоритетных прерываний, чем выполняемое в данный момент.

NO WAY !!!
А где не так??? В LPC тоже контроллер прерываний не настолько тупой.
Цитата
Правда есть нюанс, связанный с армовской архитектурой. Прерывание переключает режим ядра в IRQ.
Именно его я и имел ввиду, что дальнейшие мои слова и подтверждают. И именно для этого придумано слово __nested.

__nested и для SAM7 подойдёт, если прога для ИАРа

Цитата(Calculator)
В SAM7 можно
Попробуйте объявить простой обработчик прерываний (невложенных) и разрешить в нём прерывания. Проверьте. А потом пишите...


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
maug
сообщение Jun 6 2007, 02:45
Сообщение #9


Участник
*

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



Цитата(GetSmart @ Jun 5 2007, 17:45) *
А в каком компиляторе пишите на си?

Пишу на ICCARM 7

Цитата(Calculator @ Jun 5 2007, 17:49) *
Обработчик IRQ из IAR'овского cstartup для SAM7 отличается от обработчиков для других ARMов.


Этот код видел вот только из за особенности ICCARM асемблера не могу прикрутить аналогичную. не понимает команды работы
ldr R14, =AT91C_BASE_AIC ;Считать вектор в R0
ldr R0 , [R14, #AIC_IVR]
ldr R14, =AT91C_BASE_AIC ;Отметить окончание прерывания в
str R14, [R14, #AIC_EOICR]

Может у кого нибудь есть опыт работы ICC?

На сколько я понял с таким обработчиком, все команды (функции) тела прерывания будут использовать не IRQ стек, а общий стек лимитированный лишь размером памяти?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 6 2007, 05:37
Сообщение #10


.
******

Группа: Участник
Сообщений: 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 можно поменять.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 6 2007, 07:02
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(maug @ Jun 6 2007, 05:45) *
На сколько я понял с таким обработчиком, все команды (функции) тела прерывания будут использовать не IRQ стек,

С чего-бы это вдруг? Mode не меняли, указатель стека тоже.
Цитата
а общий стек лимитированный лишь размером памяти?

Понятия "общего стека" вообще нет. Есть конкретные стеки для режимов. Под стеки память по любому выделяется идивидуально программистом. Один (любой) из стеков неизвестного (типа сколько останется (а не вообще сколько есть!) памяти, столько и будет) размера можно конечно сделать, но это верный путь к проблемам.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 6 2007, 07:07
Сообщение #12


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



zltigo, не мутите воду. Запутаете всех окончательно. Или почитайте внимательно всё с начала.

PS Общий стек = стек основной программы.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 6 2007, 08:11
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(GetSmart @ Jun 6 2007, 10:07) *
Запутаете всех окончательно. Или почитайте внимательно всё с начала.

Если имеется конкретный кусок кода и нему конкретный вопрос ответ на который не меет отношения к этому коду, то это означает только одно - все уже запутались окончательно и без меня smile.gif
Цитата
PS Общий стек = стек основной программы.

Ну а что тогда "основная программа" - прерванная? - понимаю. Но ведь разборок с тем, из какого режима вывалились в IRQ Mode я не вижу, есть бездумная установка Supervisor Mode вне зависимости от того, какй прервали. Но основная причина моего коммента была в том, что мене не понравилось некое Ваше с maug совместное утверждение "прерывания будут использовать не IRQ стек, а общий стек лимитированный лишь размером памяти?" не только по причине мутного "общего стека", но в основном по причине того, что он "лимитированный лишь размером памяти".


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
maug
сообщение Jun 6 2007, 09:49
Сообщение #14


Участник
*

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



Эту тему я открыл, чтобы разобраться окончательно в прерываниях их приоритетах, вложениях, отсюда стеках...

Может тема уже стала несколько запутанной, может быть я совсем недавно програмирую под АРМ.
Чтобы разобраться прошу поправить если я что, то не так понимаю.

1 Основная программа и ее подпрограммы используют супервизорный стек.
2 При возникновении исключительной ситуации в нашем случае прерывание используется стек IRQ
3 Если тело обработчика использует функции то опять же используется IRQ стек (по умолчанию)
4 Для обработчика ...IRQ_Handler_Entry:... из IAR получается,что из IRQ стека используются только 4 байта (1 указатель), а далее стек переопределяется и используется супервизорный стек. Обработчик прерывания по сути представляется как обычная функция.

Приведенный в самом начале код, это лишь наглядный (осцил) эксперимент, для изучения прерываний.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 6 2007, 10:33
Сообщение #15


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



1. System обычно. Иногда User.
2. Вообще непонятно, какой такой исключительной ситуации?
3. System/User
4. Как минимум 4 байта стека IRQ, потом переключение на стек System/User


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 16:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01523 секунд с 7
ELECTRONIX ©2004-2016