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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Прерывание от таймера в AT91SAM7X256
aaarrr
сообщение May 25 2008, 10:12
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ZAA @ May 25 2008, 11:10) *
У меня не включено ни одной задачи. Просто в файле main.c инициализируется и запускается таймер.

А vTaskStartScheduler() вызывается? Без него portSAVE_CONTEXT() и portRESTORE_CONTEXT() работать правильно не будут.

Цитата(ZAA @ May 25 2008, 11:10) *
И ещё в чем разница между void vTIMER_ISR_Wrapper( void ) __attribute__((naked)); и void vTIMER_ISR_Wrapper( void ) __attribute__((interrupt("IRQ"))); ?

В первом случае компилятор не будет создавать никакого обрамления для функции, в том числе и сохранения регистров, во втором создаст обрамление для IRQ (сохранение регистров + модификация адреса возврата).
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 25 2008, 13:39
Сообщение #17


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 25 2008, 13:12) *
А vTaskStartScheduler() вызывается? Без него portSAVE_CONTEXT() и portRESTORE_CONTEXT() работать правильно не будут.
В первом случае компилятор не будет создавать никакого обрамления для функции, в том числе и сохранения регистров, во втором создаст обрамление для IRQ (сохранение регистров + модификация адреса возврата).

Спасибо за разъяснение! Это получается, мне надо для таймера отдельный Task создавать, в котором и будет таймер прерываться?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 25 2008, 15:38
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Нет, отдельный task создавать не нужно. Вы шедулер-то пробовали запускать? Работает?
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 25 2008, 16:40
Сообщение #19


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 25 2008, 18:38) *
Нет, отдельный task создавать не нужно. Вы шедулер-то пробовали запускать? Работает?

Вот только недавно получилось один раз все-таки зайти в прерывание!!!!! (благодаря Вашему совету, спасибо smile.gif ). ТОлько вот выполняется оно 1 раз (счетчик, который там внутри все время равен 1). Сейчас хоть есть от чего отталкиваться! Да, Sheduler я запускаю после вызова timer_init в файле main.c
Ещё раз спасибо! Если возникнут ещё проблемы, спрошу 05.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 25 2008, 16:43
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



CPCSTOP не забыли убрать?
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 25 2008, 18:26
Сообщение #21


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 25 2008, 19:43) *
CPCSTOP не забыли убрать?

Я понимаю, что Вам надоело наверное на такие вопросы отвечать, но все же... 05.gif
Я проверяю CPCSTOP строчкой
if((AT91C_BASE_TC1->TC_CMR && AT91C_TC_CPCSTOP) != AT91C_TC_CPCSTOP)
{
vParTestToggleLED(3);
}
Лампочка загорается, т е этот бит не равен 1.
Такое ощущение, что как-то этот самый шедулер не хочет с прерыванием нормально работать.
В файле main.c ф-ия main выглядит так:

int main( void )
{
prvSetupHardware();

timer_init();
vParTestToggleLED(0);

/* Start the scheduler.

vTaskStartScheduler();

/* We should never get here as control is now taken by the scheduler. */
return 0;
}
То есть timer_init должна вызываться один раз, потом в ней настраивается и запускается таймер и дальше он уже должен работать по прерываним?
Ф-ия timer_init выглядит так:
AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TC1);
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | AT91C_TC_WAVESEL_UP_AUTO
| AT91C_TC_WAVE;

AT91C_BASE_TC1->TC_IER = (1<<4); //прерывание RC Compare

AT91C_BASE_TC1->TC_RC = 0x00FF;

AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC1] = (unsigned int) vTIMER_ISR_Handler;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC1] = ( AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x5 );
AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_TC1);
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_TC1);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
vParTestToggleLED(1);

обработчик прерывания:
void vTIMER_ISR_Handler( void )
{
int i;
AT91PS_TC TC_pt = AT91C_BASE_TC1;
unsigned int dummy;

AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC1);

//* Acknowledge interrupt status
dummy = AT91C_BASE_TC1->TC_SR;
//* Suppress warning variable "dummy" was set but never used
dummy = dummy;

if((AT91C_BASE_TC1->TC_SR && AT91C_TC_CPCS) == AT91C_TC_CPCS)
{
vParTestToggleLED(2);
count_timer1_interrupt++;
}
AT91C_BASE_AIC->AIC_EOICR = 0x00;
}
И еще, не надо ли в конце обработчика вызывать функцию portYIELD_FROM_ISR()?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2008, 02:56
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ZAA @ May 25 2008, 22:26) *
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC1] = (unsigned int) vTIMER_ISR_Handler;

Почему здесь Handler, а не Wrapper?

Цитата(ZAA @ May 25 2008, 22:26) *
void vTIMER_ISR_Handler( void )
{
...
AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC1);

Это действие лишнее.

Цитата(ZAA @ May 25 2008, 22:26) *
И еще, не надо ли в конце обработчика вызывать функцию portYIELD_FROM_ISR()?

Не обязательно.

Цитата(ZAA @ May 25 2008, 22:26) *
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;

Это я бы разделил на две операции: trigger нужно делать, когда тактирование уже разрешено.
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 26 2008, 07:05
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 26 2008, 05:56) *
Почему здесь Handler, а не Wrapper?
Это действие лишнее.
Не обязательно.
Это я бы разделил на две операции: trigger нужно делать, когда тактирование уже разрешено.

И снова спасибо большое! бУду пробовать! smile.gif
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 26 2008, 13:00
Сообщение #24


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 26 2008, 05:56) *
Почему здесь Handler, а не Wrapper?


Большое, большое Вам спасибо!!! Дело действительно было в Wrapper! Сейчас начну с прерываниями от UART разбираться smile.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2008, 13:03
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



И Вам спасибо за отсутствие AT91F_ в исходниках wink.gif
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 27 2008, 17:31
Сообщение #26


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 26 2008, 16:03) *
И Вам спасибо за отсутствие AT91F_ в исходниках wink.gif


Уважаемый aaarrr! Для реализации прерываний USART можно пользоваться обработчиком прерывания, аналогичным обработчику таймера, т е например uart_Wrapper и uart_Handler (как у меня было с таймером)?
И ещё, имеет ли разницу, буду я использовать DBGU или же USART? Когда конфигурирую как DBGU, хотя бы посылается и принимается байт по RS232. USART же упорно не хочет работать... sad.gif 05.gif

P.S. простите за беспокойство ещё раз)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 27 2008, 18:38
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ZAA @ May 27 2008, 21:31) *
Для реализации прерываний USART можно пользоваться обработчиком прерывания, аналогичным обработчику таймера, т е например uart_Wrapper и uart_Handler (как у меня было с таймером)?

Можно так. Можно и просто оформить прерывание как
Код
void isr_handler( void ) __attribute__((interrupt("IRQ")))
{
    ...
}

если не собираетесь из прерывания вызывать шедулер.

Цитата(ZAA @ May 27 2008, 21:31) *
И ещё, имеет ли разницу, буду я использовать DBGU или же USART? Когда конфигурирую как DBGU, хотя бы посылается и принимается байт по RS232. USART же упорно не хочет работать... sad.gif 05.gif

Разницы нет практически никакой. Проверьте, разрешено ли тактирование.
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 28 2008, 03:50
Сообщение #28


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 27 2008, 21:38) *
Можно так. Можно и просто оформить прерывание как
Код
void isr_handler( void ) __attribute__((interrupt("IRQ")))
{
    ...
}

если не собираетесь из прерывания вызывать шедулер.
Разницы нет практически никакой. Проверьте, разрешено ли тактирование.

Спасибо! Буду пробовать)))
Go to the top of the page
 
+Quote Post
ZAA
сообщение May 28 2008, 17:40
Сообщение #29


Частый гость
**

Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906



Цитата(aaarrr @ May 27 2008, 21:38) *
Разницы нет практически никакой. Проверьте, разрешено ли тактирование.


Очень неудобно беспокоить Вас снова, но снова столкнулась с проблемой, вернее, с проблемами. Все те же прерывания от уарта. Пересмотрела кучу постов на эту тему, вроде все прозрачно. Надо генерировать прерывания по приему байта. Тут и начинаются косяки. Если не затруднит, не могли бы Вы помочь мне еще раз help.gif
1) Можно ли одновременно использовать и USART0, и DBGU? То есть например, прерывание конфигурировать от USART0, а посылать байт из контроллера через DBGU?
2) Почему-то срабатывают прерывание (но опять же 1 раз - ещё одна проблема) по передаче байта, по флагу RXBUFF, но не по RXRDY? На какой вообще надо настраивать?
3) Снова та же проблема - прерывание выполняется 1 раз
4) программа переходит в обработчик без какого-либо опроса буфера приемника, т е как только что-то пришло в Rx, должно произойти прерывание?
5) Обязательно ли использовать PDC?

Вот мои тексты:
Код
void init_uart(void)
{
    AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA1 | AT91C_PIO_PA0;
    AT91C_BASE_SYS->AIC_SVR[AT91C_ID_US0] = (unsigned int) vUART_ISR_Wrapper;
    //растановка приоритета прерывания
    AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63; // SRCTYPE=1, PRIOR=3. USART 0 interrupt positive edge-triggered at prio 3 //0x02;
    AT91C_BASE_SYS->AIC_IECR = (1<<AT91C_ID_US0);
    AT91C_BASE_SYS->AIC_ICCR = (1<<AT91C_ID_US0);

    *AT91C_US0_BRGR = 625;
    *AT91C_US0_MR = 0x000808C0; // Normal mode, 1 stop bit, no parity, async mode, 8 bits, MCK.
    *AT91C_US0_IDR = 0xffffffff; // Disable all USART interrupts
    *AT91C_US0_IER = AT91C_US_ENDRX; //| AT91C_US_RXBUFF;//AT91C_US_TXRDY | AT91C_US_RXRDY;

    *AT91C_US0_CR = AT91C_US_RXDIS | AT91C_US_TXDIS;
    *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN;
    *AT91C_US0_CR = AT91C_US_RSTRX | AT91C_US_RSTTX |AT91C_US_RSTSTA;
    *AT91C_PMC_PCER = (1 << AT91C_ID_US0);
}

Здесь собственно говоря смущает AT91C_BASE_SYS. Может надо настраивать как AT91C_BASE_AIC (пример настройки кстати взят из одного из постов)?

Обработчик прерывания
Код
void vUART_ISR_Handler( void )
{
    int i;
    char Tmp = *AT91C_US0_CSR;
            char *Data;
            char buffer[5];
    unsigned int status;
    status = AT91C_BASE_US0->US_CSR;
    vParTestToggleLED(Data);
    count_uart_interrupt++;
    AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTSTA;//US0->US_CR = AT91C_US_RSTSTA;
    AT91C_BASE_US0->US_CR = AT91C_US_RSTRX;//US0->US_CR = AT91C_US_RSTRX;
    AT91C_BASE_US0->US_CR = AT91C_US_RXEN;
    *AT91C_US0_IER = AT91C_US_ENDRX;
    AT91C_BASE_AIC->AIC_EOICR = 0;            // Signal end of interrupt
}

Вроде и регистр статуса считываю, и в EOICR пишу в конце. Уже и прерывание снова объявила..Ну ни в какую(((
Код
void vUART_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. */
    vParTestToggleLED(3);
    vUART_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();
}


Понимаю, что вопросы стандартные и глупые, но уже погрязла в куче информации и в доках, и в форуме, а времени остаётся все меньше и меньше crying.gif Помогите советом ещё раз, плз!!!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 28 2008, 18:21
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ZAA @ May 28 2008, 21:40) *
1) Можно ли одновременно использовать и USART0, и DBGU? То есть например, прерывание конфигурировать от USART0, а посылать байт из контроллера через DBGU?

Если скорости совпадают, то в отладочных целях можно.

Цитата(ZAA @ May 28 2008, 21:40) *
2) Почему-то срабатывают прерывание (но опять же 1 раз - ещё одна проблема) по передаче байта, по флагу RXBUFF, но не по RXRDY? На какой вообще надо настраивать?

RXBUFF будет установлен, если используется PDC. Без PDC нужно настраивать на RXRDY.

Цитата(ZAA @ May 28 2008, 21:40) *
3) Снова та же проблема - прерывание выполняется 1 раз

Возможно, из-за того, что прерывание настроено как edge sensetive.

Цитата(ZAA @ May 28 2008, 21:40) *
4) программа переходит в обработчик без какого-либо опроса буфера приемника, т е как только что-то пришло в Rx, должно произойти прерывание?

Да.

Цитата(ZAA @ May 28 2008, 21:40) *
5) Обязательно ли использовать PDC?

Нет.

Цитата(ZAA @ May 28 2008, 21:40) *
Вот мои тексты:


Я бы немного переделал:
Код
void init_uart(void)
{
    //aaarrr сначала PIO и тактирование
    AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA1 | AT91C_PIO_PA0;
    AT91C_BASE_SYS->AIC_IDCR = (1<<AT91C_ID_US0);    // на всякий случай, если UART уже использовался
    *AT91C_PMC_PCER = (1 << AT91C_ID_US0);

    //aaarrr затем собственно периферийный модуль
    // а вот здесь иногда лучше использовать макросы для битов регистров
    *AT91C_US0_BRGR = 625; // (u_int)((MCK + (UART0_BAUDRATE * 0x08)) / (UART0_BAUDRATE * 0x10)); - так может быть удобнее
    *AT91C_US0_MR = AT91C_US_USMODE_NORMAL | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE; // Normal mode, 1 stop bit, no parity, async mode, 8 bits, MCK.
    *AT91C_US0_IDR = 0xffffffff; // Disable all USART interrupts
    *AT91C_US0_IER = AT91C_US_TXRDY | AT91C_US_RXRDY;

    *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN;
    *AT91C_US0_CR = AT91C_US_RSTRX | AT91C_US_RSTTX |AT91C_US_RSTSTA;

    //aaarrr и в самом конце - прерывания
    AT91C_BASE_SYS->AIC_SVR[AT91C_ID_US0] = (unsigned int) vUART_ISR_Wrapper;
    //растановка приоритета прерывания

//    AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63; // SRCTYPE=1, PRIOR=3. USART 0 interrupt positive edge-triggered at prio 3 //0x02;
    //aaarrr Для внутренних источников лучше использовать прерывание по уровню
    AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x03; // SRCTYPE=0, PRIOR=3. USART 0 interrupt high level sensetive at prio 3

    AT91C_BASE_SYS->AIC_IECR = (1<<AT91C_ID_US0);
}


Продолжение следует...

Цитата(ZAA @ May 28 2008, 21:40) *
Здесь собственно говоря смущает AT91C_BASE_SYS. Может надо настраивать как AT91C_BASE_AIC (пример настройки кстати взят из одного из постов)?

Можно и так и так: если Вы посмотрите структуру _AT91S_SYS в файле AT91SAM7X256.h, то убедитесь, что регистры AIC на месте.
Для красоты можно, конечно, поменять.

Обработчик прерывания
Код
void vUART_ISR_Handler( void )
{
    unsigned int status;

    status = AT91C_BASE_US0->US_CSR & AT91C_BASE_US0->US_IMR; // Сразу отбросим маскированные прерывания

    vParTestToggleLED(Data);
    count_uart_interrupt++;

    if(status & AT91C_US_RXRDY)
    {
        // Делаем что нужно, но обязательно читаем US_RHR или запрещаем прерывание RXRDY
    }
    if(status & AT91C_US_TXRDY)
    {
        // Делаем что нужно, но обязательно пишем US_THR или запрещаем прерывание TXRDY
    }

    AT91C_BASE_AIC->AIC_EOICR = 0;            // Signal end of interrupt
}
Go to the top of the page
 
+Quote Post

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

 


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


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