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

Прототип обработчика прерывания

Решил попробовать воспользоваться параметром --require_prototypes и понял, что не знаю, как правильно работать с обработчиками прерываний.

 

Что должно выноситься в заголовочный файл, а что быть только в .c-файле? Как правильно описать прототип функции-обработчика прерывания?

 

На форуме пытался найти ответ на этот вопрос, но видимо, не умею правильно его задать.

 

 

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


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

Прототип функции - это объявление функции перед ее вызовом, для того чтобы компилятор мог правильно проверить типы параметров и возвращаемого значения функции. Обычно записывается в *.h и подключается include'ом в начале *.c-файла в котором используется, но можно указать и явно в начале файла:

#include <stdio.h> 
int power(int m, int n); 
/* тестирование power - функции возведения в степень */ 
main() 
{ 
int i; 
for (i = 0; i < 10; ++i) 
printf("%d %d %d\n", i, power(2,i), power(-3,i)); 
return 0; 
} 
/* power: возводит base в п-ю степень; n >= 0 */ 
int power(int base, int n) 
{ 
int i, p; 
P = 1; 
for (i = 1; i <= n; ++i) 
p = p * base; 
return p; 
}

 

Перед функцией main можно заметить такую строку:

int power(int m, int n);

Она сообщает, что power является функцией с двумя аргументами типа int, возвращающей также значение типа int. Эта декларация называется прототипом функции и обязана согласовываться по форме как с определением (заголовком) функции power, так и с любыми ее вызовами. Если определение функции отличается от ее прототипа или формы вызова, возникает ошибка.

 

Имена параметров согласовывать не обязательно. Вообще-то не обязательно даже указывать имена параметров в прототипе функции, поэтому предыдущий прототип можно было бы записать так:

int power(int, int);

Однако хорошо выбранные имена являются своеобразной документацией к программе, так что они будут часто использоваться.

 

 

Опция компилятора --require_prototypes, заставляет в обязательном порядке всем функциям иметь прототипы, иначе он выдаст ошибку

 

Прототип функции прерывания - как и у всех остальных функций

interrupt void dmaXmtIsr(void); /// <--- прототип функции
.......
void main (void)
{
......
}
......
interrupt void dmaXmtIsr(void)
{
......
.............
}

 

Подробнее - в книге Керигана/Ричи, откуда и были взяты примеры.

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

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


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

Подробнее - в книге Керигана/Ричи, откуда и были взяты примеры.

 

За изложение матчасти, конечно, спасибо, может быть, кому-то пригодится... В принципе, о прототипах я и сам могу несколько подробнее рассказать. И --require_prototypes использовал намеренно, в общем-то. Вопрос только был несколько в другом - я не совсем понимаю, как правильно объявить прототип обработчика прерывания. :fman:

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


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

В принципе, о прототипах я и сам могу несколько подробнее рассказать.

- я не совсем понимаю, как правильно объявить прототип обработчика прерывания. :fman:

 

Как-то не согласуется одно утверждение с другим :)

 

Прерывания НЕ являются частью языка Си. Их НЕЛЬЗЯ правильно объявить, пользуясь K&R Си.

 

Ибо прерывание - очень особая функция, требует особых пролога-эпилога и команду возврата.

 

Поэтому объявление прерываний абсолютно зависит от компилятора. Ищите в хелпе на компилятор.

 

В общем случае это будет

 

void UART1TransmittComplete(void);

 

А где-то рядом с ним будет ключевое слово interrupt, ISR или как там у вашего компилятора.

Также может указываться вектор прерывания (номер в таблице прерываний, или иная релевантная информация).

 

Удачи!

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


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

Вопрос только был несколько в другом - я не совсем понимаю, как правильно объявить прототип обработчика прерывания. :fman:
Пока не признаетесь, какой компилятор используете - никто помочь не сможет. Ибо, как заметил Gorby, прерывания являются расширением компилятора.

 

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


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

Пока не признаетесь, какой компилятор используете - никто помочь не сможет. Ибо, как заметил Gorby, прерывания являются расширением компилятора.

 

ИАР, на данный момент работает так:

 

 

#pragma vector=USART0_RX_vect
__interrupt void usart_rx_complete ( void );


...

#pragma vector=USART0_RX_vect
__interrupt void usart_rx_complete ( void )
{
  // If buffer not overflowed
  if ( rbuf_RX.ui_Len < USART_BUF_SIZE )
  {
    rbuf_RX.uc_Data[rbuf_RX.ui_Next] = UDR;
    // Incrementing buffer counters and pointers
    rbuf_RX.ui_Len += 1;
    rbuf_RX.ui_Next += 1;
    // Check for pointer to next is in range 
    if ( rbuf_RX.ui_Next == USART_BUF_SIZE )
      rbuf_RX.ui_Next = 0;
    }
}

 

но это не более, чем эмпирическим путем полученная компиляция без ошибок. Ни подтверждения, ни опровержения правильности такого использования найти не смог.

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


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

//--------------------------- 
// IAR - AVR IAR Compiler [ICCAVR] (Current Version) 

// required includes 
#include <processor-specific include> 
#include <inavr.h> // Architecture include 
// brings in __enable_interrupt() and __disable_interrupt() 
// not requred for the ISR itself, but will be needed to 
// enable interrupts in your code 

//handler declaration 
#pragma vector=interrupt-vector-name 
__interrupt void my_name_for_this_isr(void) { 
   //rest of code 
} 
// NOTE: The ISR function must immediately follow the #pragma

 

Все верно. Вы случайно угадали правильный синтаксис.

 

http://www.avrfreaks.net/index.php?name=PN...pic&t=54318

 

Загляните по ссылке, как раз для Вас.

А вообще - читать доку на компилятор. Там много есть интересного.

 

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


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

Все верно. Вы случайно угадали правильный синтаксис.

 

Вы привели пример declaration, меня же интересует definition... И случай с interrupt definition или что-то подобное я действительно не могу найти в "IAR C/C++ Compiler Reference Guide for Atmel® Corporation’s AVR Microcontroller Family" :blink:

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


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

Вы привели пример declaration, меня же интересует definition...

Не знаю почему написано declaration, это definition и есть.

 

И случай с interrupt definition или что-то подобное я действительно не могу найти в "IAR C/C++ Compiler Reference Guide for Atmel® Corporation’s AVR Microcontroller Family" :blink:

Из EWAVR_CompilerReference.pdf

 

Defining an interrupt function—an example

To define an interrupt function, the __interrupt keyword and the #pragma vector

directive can be used. For example:

#pragma vector = 0x14

__interrupt void MyInterruptRoutine(void)

{

/* Do something */

}

Note: An interrupt function must have the return type void, and it cannot specify any

parameters

 

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


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

Не знаю почему написано declaration, это definition и есть.

 

Действительно... Но опять же, не совсем так. Это definition with declaration скорее :) То есть сразу объявление и описание. Равносильно записи

char x=1;

; И этот фрагмент, в том числе, приведенный Вами из EWAVR_CompilerReference.pdf - по сути, должен находиться в .c-файле. Вопрос сводится к тому, как его "упомянуть" в .h-файле?

 

 

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


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

Вопрос сводится к тому, как его "упомянуть" в .h-файле?

А оно надо?

 

__interrupt void MyInterruptRoutine(void);

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


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

А оно надо?
Допустим, ну очень хочется откомпилироваться с --require_prototypes
__interrupt void MyInterruptRoutine(void);

Смею не согласиться: Warning[Ta006]: Interrupt function has no assigned vector. C:\asp\asp_Prj\sms\USART.h 64 

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


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

Допустим, ну очень хочется откомпилироваться с --require_prototypes Смею не согласиться: Warning[Ta006]: Interrupt function has no assigned vector. C:\asp\asp_Prj\sms\USART.h 64 

Тогда так:

 

#pragma vector=TIMER3_COMPA_vect
__interrupt void timer_1khz_isr(void);

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


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

Тогда так:

 

#pragma vector=TIMER3_COMPA_vect
__interrupt void timer_1khz_isr(void);

 

Вот я тоже на таком варианте остановился (см мои предыдущие сообщения), но как-то метод тыка, хоть и научного, не очень устраивает :w00t: хотелось бы понять, как действительно должно быть.

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


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

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

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

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

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

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

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

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

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

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