|
|
  |
Прерывание от таймера в AT91SAM7X256 |
|
|
|
May 25 2008, 10:12
|
Гуру
     
Группа: Свой
Сообщений: 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 (сохранение регистров + модификация адреса возврата).
|
|
|
|
|
May 25 2008, 13:39
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 25 2008, 13:12)  А vTaskStartScheduler() вызывается? Без него portSAVE_CONTEXT() и portRESTORE_CONTEXT() работать правильно не будут. В первом случае компилятор не будет создавать никакого обрамления для функции, в том числе и сохранения регистров, во втором создаст обрамление для IRQ (сохранение регистров + модификация адреса возврата). Спасибо за разъяснение! Это получается, мне надо для таймера отдельный Task создавать, в котором и будет таймер прерываться?
|
|
|
|
|
May 25 2008, 16:40
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 25 2008, 18:38)  Нет, отдельный task создавать не нужно. Вы шедулер-то пробовали запускать? Работает? Вот только недавно получилось один раз все-таки зайти в прерывание!!!!! (благодаря Вашему совету, спасибо  ). ТОлько вот выполняется оно 1 раз (счетчик, который там внутри все время равен 1). Сейчас хоть есть от чего отталкиваться! Да, Sheduler я запускаю после вызова timer_init в файле main.c Ещё раз спасибо! Если возникнут ещё проблемы, спрошу
|
|
|
|
|
May 25 2008, 18:26
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 25 2008, 19:43)  CPCSTOP не забыли убрать? Я понимаю, что Вам надоело наверное на такие вопросы отвечать, но все же... Я проверяю 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()?
|
|
|
|
|
May 26 2008, 02:56
|
Гуру
     
Группа: Свой
Сообщений: 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 нужно делать, когда тактирование уже разрешено.
|
|
|
|
|
May 26 2008, 07:05
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 26 2008, 05:56)  Почему здесь Handler, а не Wrapper? Это действие лишнее. Не обязательно. Это я бы разделил на две операции: trigger нужно делать, когда тактирование уже разрешено. И снова спасибо большое! бУду пробовать!
|
|
|
|
|
May 26 2008, 13:00
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 26 2008, 05:56)  Почему здесь Handler, а не Wrapper? Большое, большое Вам спасибо!!! Дело действительно было в Wrapper! Сейчас начну с прерываниями от UART разбираться
|
|
|
|
|
May 27 2008, 17:31
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 26 2008, 16:03)  И Вам спасибо за отсутствие AT91F_ в исходниках  Уважаемый aaarrr! Для реализации прерываний USART можно пользоваться обработчиком прерывания, аналогичным обработчику таймера, т е например uart_Wrapper и uart_Handler (как у меня было с таймером)? И ещё, имеет ли разницу, буду я использовать DBGU или же USART? Когда конфигурирую как DBGU, хотя бы посылается и принимается байт по RS232. USART же упорно не хочет работать... P.S. простите за беспокойство ещё раз)
|
|
|
|
|
May 27 2008, 18:38
|
Гуру
     
Группа: Свой
Сообщений: 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 же упорно не хочет работать...  Разницы нет практически никакой. Проверьте, разрешено ли тактирование.
|
|
|
|
|
May 28 2008, 03:50
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 27 2008, 21:38)  Можно так. Можно и просто оформить прерывание как Код void isr_handler( void ) __attribute__((interrupt("IRQ"))) { ... } если не собираетесь из прерывания вызывать шедулер. Разницы нет практически никакой. Проверьте, разрешено ли тактирование. Спасибо! Буду пробовать)))
|
|
|
|
|
May 28 2008, 17:40
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 10-02-08
Из: Екб
Пользователь №: 34 906

|
Цитата(aaarrr @ May 27 2008, 21:38)  Разницы нет практически никакой. Проверьте, разрешено ли тактирование. Очень неудобно беспокоить Вас снова, но снова столкнулась с проблемой, вернее, с проблемами. Все те же прерывания от уарта. Пересмотрела кучу постов на эту тему, вроде все прозрачно. Надо генерировать прерывания по приему байта. Тут и начинаются косяки. Если не затруднит, не могли бы Вы помочь мне еще раз 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(); } Понимаю, что вопросы стандартные и глупые, но уже погрязла в куче информации и в доках, и в форуме, а времени остаётся все меньше и меньше  Помогите советом ещё раз, плз!!!
|
|
|
|
|
May 28 2008, 18:21
|
Гуру
     
Группа: Свой
Сообщений: 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 }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|