ZAA 0 Posted May 22, 2008 · Report post Используем FreeRTOS. ВОзникла необходимость использования таймера. Вроде просто так таймер запускается и работает, а вот прерывания не обрабатывает. Я подозреваю, что функцию обработки прерывания нельзя объявлять, как обычную функцию. Наверное, надо прописывать ещё вектор прерывания от таймера где-то там. В том и проблема, что не очень хорошо разбираюсь во всяких там секциях памяти, размещении векторов и т. д (по крайней мере в этом контроллере). Как бы это попроще организовать??? ТЕкст (кстати стандартный) приведен ниже: //ф-ия обработки прерывания 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
aaarrr 0 Posted May 22, 2008 · Report post Я подозреваю, что функцию обработки прерывания нельзя объявлять, как обычную функцию. Нельзя. Как правильно объявить прерывание ищите в документации на компилятор. P.S. Знаю, что подобные посты уже были, но хотелось бы ещё раз остановиться на данной проблеме! Спасибо заранее за ответы. Были уже сотню раз. Пользуйтесь поиском. Share this post Link to post Share on other sites
_4afc_ 0 Posted May 22, 2008 (edited) · Report post Нельзя. Как правильно объявить прерывание ищите в документации на компилятор. Были уже сотню раз. Пользуйтесь поиском. А вот в WinARM обработчики - это обычные функции. Ибо вход в во все прерывания всё-равно один и далее ваша функция вызывается как обычная подпрограмма. Надо только поместить указатель на подпрограмму в соответствующий регистр AIC, что делает не компилятор, а специальная подпрограмма AT91F_AIC_ConfigureIt. Разница в выходе из обработчика, только в прерываниях по уровню и фронту. Надо смотреть какой реализован за вас. Edited May 22, 2008 by _4afc_ Share this post Link to post Share on other sites
aaarrr 0 Posted May 22, 2008 · Report post Обработчики - это обычные функции. Ибо вход в во все прерывания всё-равно один и далее ваша функция вызывается как обычная подпрограмма. Представьте себе, далеко не всегда. Более того, обработчики обычно вызываются именно в IRQ режиме. А то, как именно будет вызвана функция, определяется кодом, стартующим с адреса 0x18. Надо только поместить указатель на подпрограмму в соответствующий регистр AIC, что делает не компилятор, а специальная подпрограмма AT91F_AIC_ConfigureIt. У любителей использования "специальных подпрограмм AT91F_" обычно плохо с мат. частью. Разница в выходе из обработчика, только в прерываниях по уровню и фронту. Надо смотреть какой реализован за вас. Чушь. Не путайте божый дар (ARM) с яичницей(AVR). Share this post Link to post Share on other sites
ZAA 0 Posted May 22, 2008 · Report post НУ вот, ничего конкретного... :crying: а ведь хотя бы один маааленький совет может натолкнуть на верный путь Share this post Link to post Share on other sites
aaarrr 0 Posted May 22, 2008 · Report post Чтобы получить маааленький совет, укажите: 1. Какой используется компилятор. 2. Какой порт FreeRTOS. Share this post Link to post Share on other sites
ZAA 0 Posted May 22, 2008 · Report post Чтобы получить маааленький совет, укажите: 1. Какой используется компилятор. 2. Какой порт FreeRTOS. Я делаю проект в Eclipse для AT91SAM7X256. А компилятор - gcc (который из эклипсовского gnu-армовского набора инструментов). Пыталась найти что-то подобное в инфе про gcc, но безрезультатно...Видимо, или ищу не там, или не то... А вообще без отладчика тяжко программу писать... Share this post Link to post Share on other sites
sla000 0 Posted May 23, 2008 · Report post Я делаю проект в Eclipse для AT91SAM7X256. А компилятор - gcc (который из эклипсовского gnu-армовского набора инструментов). Пыталась найти что-то подобное в инфе про gcc, но безрезультатно...Видимо, или ищу не там, или не то... А вообще без отладчика тяжко программу писать... Тяжело но можно, а потом когда привыкаешь так даже проще ) По вашему случаю рекомендую этот код компилить в ARM режиме, либо разделить код на 2 части и в ARM компилить функцию прерывания, а в THUMB (в котором скомпилен FreeRTOS для SAM7X256) скомпилировать все остальное. Кроме того обратите внимание как обрамлен код прерывания в уже имеющихся прерываниях FreeRTOS. То как сделано сейчас просто уронит ось когда наконец заработает. Share this post Link to post Share on other sites
ZAA 0 Posted May 23, 2008 (edited) · Report post Тяжело но можно, а потом когда привыкаешь так даже проще ) По вашему случаю рекомендую этот код компилить в ARM режиме, либо разделить код на 2 части и в ARM компилить функцию прерывания, а в THUMB (в котором скомпилен FreeRTOS для SAM7X256) скомпилировать все остальное. Кроме того обратите внимание как обрамлен код прерывания в уже имеющихся прерываниях FreeRTOS. То как сделано сейчас просто уронит ось когда наконец заработает. спасибо вам! Я попробую. Ещё встречный вопрос. Надо секцию, отвечающую за прерывания. размещать в Csatartup.c? Там же где и секции .text, .bss? Может быть. вы мне подскажете какой-нибудь источник, в котором хотя бы в общих словах рассказывается о принципах написания ассемблерных файлов для этого контроллера. ну в смысле всяких там секций и т п, а то с этим туговато. а без этого никак :crying: Спасибо! И ещё: что вы имеете ввиду под "То как сделано сейчас просто уронит ось когда наконец заработает"? Edited May 23, 2008 by ZAA Share this post Link to post Share on other sites
sla000 0 Posted May 23, 2008 · Report post Надо секцию, отвечающую за прерывания. размещать в 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
ZAA 0 Posted May 24, 2008 · Report post Нет, гляньте в мейкфайл, там есть список файлов 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
ZAA 0 Posted May 24, 2008 · Report post Нет, гляньте в мейкфайл, там есть список файлов 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 ; } В чем косяк может быть? Помогите пожалуйста!!! Share this post Link to post Share on other sites
KolyanV 0 Posted May 24, 2008 · Report post В чем косяк может быть? Помогите пожалуйста!!! Не уверен, но, может быть, вместо AT91C_BASE_AIC->AIC_EOICR = 0; надо AT91C_BASE_AIC->AIC_EOICR =AT91C_ID_TC1; Share this post Link to post Share on other sites
aaarrr 0 Posted May 24, 2008 · Report post 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
ZAA 0 Posted May 25, 2008 · Report post 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