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

Прерывание от таймера в AT91SAM7X256

Используем FreeRTOS. ВОзникла необходимость использования таймера. Вроде просто так таймер запускается и работает, а вот прерывания не обрабатывает. Я подозреваю, что функцию обработки прерывания нельзя объявлять, как обычную функцию. Наверное, надо прописывать ещё вектор прерывания от таймера где-то там. В том и проблема, что не очень хорошо разбираюсь во всяких там секциях памяти, размещении векторов и т. д (по крайней мере в этом контроллере). Как бы это попроще организовать??? :help:

ТЕкст (кстати стандартный) приведен ниже:

//ф-ия обработки прерывания

void timer1_c_irq_handler(void)

{

AT91PS_TC TC_pt = AT91C_BASE_TC1;

unsigned int dummy;

//* Acknowledge interrupt status

dummy = TC_pt->TC_SR;

//* Suppress warning variable "dummy" was set but never used

dummy = dummy;

count_timer0_interrupt++;

vParTestToggleLED( 2 );

}

 

void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)

{

unsigned int dummy;

AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ) ;

AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TC1);

TC_pt->TC_CCR = AT91C_TC_CLKDIS ;

TC_pt->TC_IDR = 0xFFFFFFFF ;

 

dummy = TC_pt->TC_SR;

 

TC_pt->TC_CMR = Mode ;

 

TC_pt->TC_CCR = AT91C_TC_CLKEN ;

}

 

void timer_init ( void )

{

unsigned int oldHandler;

unsigned int mask ;

AT91S_AIC *pAIC = AT91C_BASE_AIC;

AT91S_TC *pTMR = AT91C_BASE_TC1;

 

//init the timer interrupt counter

count_timer0_interrupt=0;

count_timer1_interrupt=0;

 

//* Open timer1

AT91F_TC_Open(AT91C_BASE_TC1,TC_CLKS_MCK128,AT91C_ID_TC1);

 

//* Open Timer 1 interrupt

AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC1, TIMER1_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer1_c_irq_handler);

AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC

AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC1);

 

//* Start timer1

//AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG ;

 

}

 

P.S. Знаю, что подобные посты уже были, но хотелось бы ещё раз остановиться на данной проблеме! Спасибо заранее за ответы.

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


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

Я подозреваю, что функцию обработки прерывания нельзя объявлять, как обычную функцию.

Нельзя. Как правильно объявить прерывание ищите в документации на компилятор.

 

P.S. Знаю, что подобные посты уже были, но хотелось бы ещё раз остановиться на данной проблеме! Спасибо заранее за ответы.

Были уже сотню раз. Пользуйтесь поиском.

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


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

Нельзя. Как правильно объявить прерывание ищите в документации на компилятор.

Были уже сотню раз. Пользуйтесь поиском.

А вот в WinARM обработчики - это обычные функции. Ибо вход в во все прерывания всё-равно один и далее ваша функция вызывается как обычная подпрограмма. Надо только поместить указатель на подпрограмму в соответствующий регистр AIC, что делает не компилятор, а специальная подпрограмма AT91F_AIC_ConfigureIt.

Разница в выходе из обработчика, только в прерываниях по уровню и фронту.

Надо смотреть какой реализован за вас.

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

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


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

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

Представьте себе, далеко не всегда. Более того, обработчики обычно вызываются именно в IRQ режиме. А то, как именно будет вызвана функция, определяется кодом, стартующим с адреса 0x18.

 

Надо только поместить указатель на подпрограмму в соответствующий регистр AIC, что делает не компилятор, а специальная подпрограмма AT91F_AIC_ConfigureIt.

У любителей использования "специальных подпрограмм AT91F_" обычно плохо с мат. частью.

 

Разница в выходе из обработчика, только в прерываниях по уровню и фронту.

Надо смотреть какой реализован за вас.

Чушь.

 

Не путайте божый дар (ARM) с яичницей(AVR).

:lol:

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


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

НУ вот, ничего конкретного... :crying: а ведь хотя бы один маааленький совет может натолкнуть на верный путь

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


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

Чтобы получить маааленький совет, укажите:

1. Какой используется компилятор.

2. Какой порт FreeRTOS.

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


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

Чтобы получить маааленький совет, укажите:

1. Какой используется компилятор.

2. Какой порт FreeRTOS.

 

Я делаю проект в Eclipse для AT91SAM7X256. А компилятор - gcc (который из эклипсовского gnu-армовского набора инструментов). Пыталась найти что-то подобное в инфе про gcc, но безрезультатно...Видимо, или ищу не там, или не то...

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

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


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

Я делаю проект в Eclipse для AT91SAM7X256. А компилятор - gcc (который из эклипсовского gnu-армовского набора инструментов). Пыталась найти что-то подобное в инфе про gcc, но безрезультатно...Видимо, или ищу не там, или не то...

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

 

Тяжело но можно, а потом когда привыкаешь так даже проще )

 

По вашему случаю рекомендую этот код компилить в ARM режиме, либо разделить код на 2 части и в ARM компилить функцию прерывания, а в THUMB (в котором скомпилен FreeRTOS для SAM7X256) скомпилировать все остальное. Кроме того обратите внимание как обрамлен код прерывания в уже имеющихся прерываниях FreeRTOS. То как сделано сейчас просто уронит ось когда наконец заработает.

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


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

Тяжело но можно, а потом когда привыкаешь так даже проще )

 

По вашему случаю рекомендую этот код компилить в ARM режиме, либо разделить код на 2 части и в ARM компилить функцию прерывания, а в THUMB (в котором скомпилен FreeRTOS для SAM7X256) скомпилировать все остальное. Кроме того обратите внимание как обрамлен код прерывания в уже имеющихся прерываниях FreeRTOS. То как сделано сейчас просто уронит ось когда наконец заработает.

спасибо вам! Я попробую. Ещё встречный вопрос. Надо секцию, отвечающую за прерывания. размещать в Csatartup.c? Там же где и секции .text, .bss? Может быть. вы мне подскажете какой-нибудь источник, в котором хотя бы в общих словах рассказывается о принципах написания ассемблерных файлов для этого контроллера. ну в смысле всяких там секций и т п, а то с этим туговато. а без этого никак :crying: Спасибо!

И ещё: что вы имеете ввиду под "То как сделано сейчас просто уронит ось когда наконец заработает"?

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

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


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

Надо секцию, отвечающую за прерывания. размещать в Csatartup.c? Там же где и секции .text, .bss?

 

Нет, гляньте в мейкфайл, там есть список файлов SRC и SRCARM, так вот, если вы создадите файлик с телом перывания, то его надо добавить в список SRCARM. Так он скомпилится в ARM режиме. Соответсвенно всю остальную требуху - инициализацию таймера и т.п. можно запихнуть в SRC, тогда они скомпилятся в THUMB.

 

Может быть. вы мне подскажете какой-нибудь источник, в котором хотя бы в общих словах рассказывается о принципах написания ассемблерных файлов для этого контроллера. ну в смысле всяких там секций и т п, а то с этим туговато. а без этого никак :crying: Спасибо!

 

Да не переживайте вы так ) зачем вам вообще надо программировать на асме? Ну если уж так интересно читайте документацию на архитектуру ARM7TDMI есть на сайте ATMEL.

 

И ещё: что вы имеете ввиду под "То как сделано сейчас просто уронит ось когда наконец заработает"?

 

У FreeRTOS есть совершенно четкие указания как должно выглядеть прерывание. Если им не следовать результат непредсказуем, но 100% что все пойдет не так как должно. Как должно быть обрамлено прерывание можно почитать тут:

http://www.freertos.org/portsam7xlwIP.html

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


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

Нет, гляньте в мейкфайл, там есть список файлов SRC и SRCARM, так вот, если вы создадите файлик с телом перывания, то его надо добавить в список SRCARM. Так он скомпилится в ARM режиме. Соответсвенно всю остальную требуху - инициализацию таймера и т.п. можно запихнуть в SRC, тогда они скомпилятся в THUMB.

Да не переживайте вы так ) зачем вам вообще надо программировать на асме? Ну если уж так интересно читайте документацию на архитектуру ARM7TDMI есть на сайте ATMEL.

У FreeRTOS есть совершенно четкие указания как должно выглядеть прерывание. Если им не следовать результат непредсказуем, но 100% что все пойдет не так как должно. Как должно быть обрамлено прерывание можно почитать тут:

http://www.freertos.org/portsam7xlwIP.html

Огромное Вам спасибо! Я постараюсь разобраться!!!

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


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

Нет, гляньте в мейкфайл, там есть список файлов SRC и SRCARM, так вот, если вы создадите файлик с телом перывания, то его надо добавить в список SRCARM. Так он скомпилится в ARM режиме. Соответсвенно всю остальную требуху - инициализацию таймера и т.п. можно запихнуть в SRC, тогда они скомпилятся в THUMB.

 

Уважаемый sla000!!! Я следую Вашим советам, но все равно не хочет этот таймер рботать. Уж руки просто опускаются!

Я объявляю в файлике interrupt_timer (который компилируется в ARM-mode) 2 функции (как сказано на сайте фриртоса):

 

void vTIMER_ISR_Handler( void )

{

portBASE_TYPE xTaskWokenByPost = pdFALSE;

static volatile unsigned portLONG ulNextMessage = 0;

xISRStatus *pxMessage;

AT91PS_TC TC_pt = AT91C_BASE_TC1;

unsigned int dummy;

//* Acknowledge interrupt status

dummy = TC_pt->TC_SR;

//* Suppress warning variable "dummy" was set but never used

dummy = dummy;

count_timer1_interrupt++;

vParTestToggleLED(3);

AT91C_BASE_AIC->AIC_EOICR = 0;

}

void vTIMER_ISR_Wrapper( void )

{

/* Save the context of the interrupted task. */

portSAVE_CONTEXT();

 

/* Call the handler itself. This must be a separate function as it uses

the stack. */

vTIMER_ISR_Handler();

 

/* Restore the context of the task that is going to

execute next. This might not be the same as the originally

interrupted task.*/

portRESTORE_CONTEXT();

}

 

Обе эти функции объявлены в файле interrupt_timer.h так:

void vTIMER_ISR_Wrapper( void ) __attribute__((naked));

void vTIMER_ISR_Handler( void );

 

Потом в init_timer.c (компилируется в THUMB-mode) настраиваю таймер1 (тоже вроде стандартная последовательность) и вызываю обработчик прерывания:

void timer_init ( void )

//* Begin

{

AT91S_AIC *pAIC = AT91C_BASE_AIC;

AT91S_TC *pTMR = AT91C_BASE_TC1;

//* Open timer1

AT91F_TC_Open(AT91C_BASE_TC1,TC_CLKS_MCK128,AT91C_ID_TC1);

AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TC1);

AT91C_BASE_TC1->TC_CMR=AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_CPCSTOP;

 

//* Open Timer 1 interrupt

AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC1, TIMER0_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) )vTIMER_ISR_Wrapper);

//AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC

AT91C_BASE_TC1->TC_RC = 0xFFFF;

//AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC1);

 

AT91C_BASE_TC1->TC_CCR=AT91C_TC_CLKEN;

AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG ;

}

 

В чем косяк может быть? :help: Помогите пожалуйста!!!

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


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

В чем косяк может быть? :help: Помогите пожалуйста!!!

Не уверен, но, может быть, вместо

AT91C_BASE_AIC->AIC_EOICR = 0;

надо

AT91C_BASE_AIC->AIC_EOICR =AT91C_ID_TC1;

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


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

AT91F_TC_Open(AT91C_BASE_TC1,TC_CLKS_MCK128,AT91C_ID_TC1);

AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TC1);

AT91C_BASE_TC1->TC_CMR=AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_CPCSTOP;

Timer1 сконфигурирован в Capture Mode, а бит CPCSTOP существует в Waveform Mode.

 

//AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC

AT91C_BASE_TC1->TC_RC = 0xFFFF;

//AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC1);

Присутствующим остается только гадать, почему разрешение оказалось закомментировано?

 

 

P.S. OFF. Еще раз пройдусь по AT91F_: Человеки! Ну зачем вы пользуетесь этой дрянью? Ведь код становится понять совершенно невозможно, а жизнь они никак облегчить не могут в силу своей примитивности.

 

Не уверен, но, может быть

Не может. В EOICR можно писать что угодно.

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


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

Timer1 сконфигурирован в Capture Mode, а бит CPCSTOP существует в Waveform Mode.

Присутствующим остается только гадать, почему разрешение оказалось закомментировано?

P.S. OFF. Еще раз пройдусь по AT91F_: Человеки! Ну зачем вы пользуетесь этой дрянью? Ведь код становится понять совершенно невозможно, а жизнь они никак облегчить не могут в силу своей примитивности.

Поправки в настройке таймера не помогли :crying: Не хочет он прерываться. У меня не включено ни одной задачи. Просто в файле main.c инициализируется и запускается таймер. Такое подозрение, что тут сама ОС не дает ему запуститься... И ещё в чем разница между void vTIMER_ISR_Wrapper( void ) __attribute__((naked)); и void vTIMER_ISR_Wrapper( void ) __attribute__((interrupt("IRQ"))); ?

КАк не навредить-то собственным FreeRTOSовским перрываниям и получить это несчастное прерывание по таймеру, например по TC1 (ну или TC0)???

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


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

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

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

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

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

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

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

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

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

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