Jump to content

    

Прерывание от таймера в 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. Знаю, что подобные посты уже были, но хотелось бы ещё раз остановиться на данной проблеме! Спасибо заранее за ответы.

Share this post


Link to post
Share on other sites
Я подозреваю, что функцию обработки прерывания нельзя объявлять, как обычную функцию.

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

 

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

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

Share this post


Link to post
Share on other sites
Нельзя. Как правильно объявить прерывание ищите в документации на компилятор.

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

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

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

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

Edited by _4afc_

Share this post


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

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

 

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

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

 

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

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

Чушь.

 

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

:lol:

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites
Чтобы получить маааленький совет, укажите:

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

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

 

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

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

Share this post


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

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

 

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

 

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

Share this post


Link to post
Share on other sites
Тяжело но можно, а потом когда привыкаешь так даже проще )

 

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

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

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

Edited by ZAA

Share this post


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

 

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

 

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

 

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

 

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

 

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

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

Share this post


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

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

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

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

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

Share this post


Link to post
Share on other sites
Нет, гляньте в мейкфайл, там есть список файлов 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: Помогите пожалуйста!!!

Share this post


Link to post
Share on other sites
В чем косяк может быть? :help: Помогите пожалуйста!!!

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

AT91C_BASE_AIC->AIC_EOICR = 0;

надо

AT91C_BASE_AIC->AIC_EOICR =AT91C_ID_TC1;

Share this post


Link to post
Share on other sites
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 можно писать что угодно.

Share this post


Link to post
Share on other sites
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)???

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this