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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> проблема - uCos и USART IRQ handler, не могу нормально запустить свой обработчик прерывания в uCos-e
_dem
сообщение Mar 2 2007, 16:14
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



Добрый день, уважаемый ALL

Разбираюсь с micrium OS - пожалуйста, ткните носом в страницу мануала.
мозги уже кипят - видимо, чего-то упорно не хотят замечать sad.gif

Проблема в следующем - при попытке навесить свой обработчик прерывания на ком-порт под uCos-ом задача работает до первого вызова OSTimeDlyHMSM(), потом все зависает в цикле OS_TaskIdle().

вот код, запускающий обработчик

Код
    AT91F_AIC_ConfigureIt( AT91C_BASE_AIC,   AT91C_ID_US0, 7 , AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL  | AT91C_AIC_PRIOR_LOWEST, usart0_irq_handler);  
    AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_US0);


вот сам обработчик

Код
void usart0_irq_handler(void)
{
        // calling irq processor
        if (_comports [ 0 ])
                {
                 _comports [ 0 ] -> __irq_processor();
                }
/////////////////////
    unsigned long rx_data                     = AT91C_BASE_PITC->PITC_PIVR;   /* Read the interrupt source, ignore the value*/

    AT91C_BASE_AIC->AIC_IVR     = 0;                            /* Debug variant of IVR (protect mode is used)*/
    AT91C_BASE_AIC->AIC_ICCR    = AT91C_ID_US0;                 /* Clear  USART0 interrupt                    */
    AT91C_BASE_AIC->AIC_EOICR   = 0;                            /* Signal end of interrupt                    */

       //* Reset the satus bit
AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;  

}


Если убрать вызов
Код
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_US0);

т.е. не включать прерывание в AIC, то все работает - понятно, кроме собственно обработчика.

видимо, ошибся в обработчике, но не могу понять - где ?

----
добавил в обработчик вызовы OSIntEnter() / OSIntExit() - не помогло sad.gif

Сообщение отредактировал _dem - Mar 2 2007, 16:56
Go to the top of the page
 
+Quote Post
AlexBoy
сообщение Mar 2 2007, 19:55
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394



Там цепочка вызовов такая: с вектора 0x18 вызввается общий асмовский обработчик OS_CPU_IRQ_ISR_Handler в файле os_cpu_a.s, затем из него общий сишный обработчик, у меня он такой:
Код
void OS_CPU_IRQ_ISR_Handler(void)
  {
    pFNCT pfnct;
  
    pfnct = (pFNCT)*AT91C_AIC_IVR;   // Чтение адреса обработчика с максимальным приоритетом

    AT91C_BASE_AIC->AIC_IVR = 0;                // Debug variant of vector read (protect mode is used)
    if (pfnct) pfnct();                         // Вызвать обработчик
    AT91C_BASE_AIC->AIC_EOICR = 0;              // Признак завершения обработчика
  }


а из него уже обработчик конкретного устройства
Код
void UART0_IRQ_Handler(void)
  {
    BYTE data;
    AT91PS_USART pCOM;
    DWORD status;

    // читаем регистр состояния в соотв. с текущим прерыванием
    status = pCOM->US_CSR;
    
    // Есть принятый байт
    if (status & AT91C_US_RXRDY)
      {
        data = pCOM->US_RHR;
        if (!(status & AT91C_US_FRAME))
          {
            QueueAdd(RxQueue, data);
          }
      }
    ....  

    // timeout приема
    if (status & AT91C_US_TIMEOUT)
      {
       // начать новый отсчет
        pCOM->US_CR = AT91C_US_RETTO;
      }  
      
    // очистить признаки ошибок
    pCOM->US_CR = AT91C_US_RSTSTA;
    // Разбудить задачу
    OSMboxPost(TabloMsg, (void*)1);
  }

Прикрепленные файлы
Прикрепленный файл  os_cpu_a.zip ( 3.61 килобайт ) Кол-во скачиваний: 41
 
Go to the top of the page
 
+Quote Post
_dem
сообщение Mar 5 2007, 11:48
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



с этим я разобрался, спасибо

но все равно не работает sad.gif где может быть собака зарыта ?
Go to the top of the page
 
+Quote Post
AlexBoy
сообщение Mar 5 2007, 13:06
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394



Цитата(_dem @ Mar 5 2007, 10:48) *
с этим я разобрался, спасибо

но все равно не работает sad.gif где может быть собака зарыта ?


ну вообще похоже, что прерывания были выключены и не включились обратно
Go to the top of the page
 
+Quote Post
_dem
сообщение Mar 5 2007, 13:13
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



Цитата(AlexBoy @ Mar 5 2007, 14:06) *
Цитата(_dem @ Mar 5 2007, 10:48) *

с этим я разобрался, спасибо

но все равно не работает sad.gif где может быть собака зарыта ?


ну вообще похоже, что прерывания были выключены и не включились обратно


ситуация такая, что мой таск работает до тех пор, пока я не передам каким-либо образом управление другому таску - например, задаче IdleTask при вызове функции OSTimeDly()...

обратно управление не передается sad.gif
Go to the top of the page
 
+Quote Post
AlexBoy
сообщение Mar 5 2007, 19:08
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394



Цитата(_dem @ Mar 5 2007, 12:13) *
ситуация такая, что мой таск работает до тех пор, пока я не передам каким-либо образом управление другому таску - например, задаче IdleTask при вызове функции OSTimeDly()...

обратно управление не передается sad.gif


Из IdleTask вызов шедулера происходит по прерыванию таймера. Нету прерывания, соответственно остается вечно в IdleTask. Возможно OS_EXIT_CRITICAL где-то забыл.
Go to the top of the page
 
+Quote Post
_dem
сообщение Mar 6 2007, 10:46
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



пока ничего нового sad.gif роюсь в документации и сырцах

сделал 2 своих обработчика прерывания - таймера и usart.
естественно, из обработчика PIT вызываю старый обработчик - чтобы оська работала

включаем свой обработчик таймера - все работает нормально, все переключается
включаем свой обработчик USART - все валится, конкретно - не работает таймер, и, видимо, остальные прерывание тоже не обрабатываются... код одинаковый, за исключением, понятно, констант идентификации периферии ID_US0.

help.gif ! cranky.gif

включаем ISR USART :
Код
void InitUSART (void) {

  // Enable interrupts
  // Disable the interrupt on the interrupt controller
  AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_US0);
  // Save the interrupt handler routine pointer and the interrupt priority
  void * ptr  = 0;
  ptr = (void *)(unsigned long)AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0];
  *(unsigned long *)&old_usart_handlers[0] = (unsigned long)ptr;
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0] = (unsigned long) USART0_ISR_Handler;
  // Store the Source Mode Register
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
  // Clear the interrupt on the interrupt controller
  AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_US0);
  // disable all interrupts on USART
  AT91C_BASE_US0->US_IDR = 0xFFFFFFFF;
  // Enable the interrupt on the interrupt controller

  AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_US0);
  // Enable the interrupt on the USART
      return;



}


USART ISR :
Код
static  void  USART0_ISR_Handler (void)
{
    CPU_INT32U      status;

    if (blink) {
        AT91C_BASE_PIOA->PIO_SODR = (1<<13);
        AT91C_BASE_PIOB->PIO_SODR = (1<<26);
    blink = 0;
    }
    else
    {
        AT91C_BASE_PIOA->PIO_CODR = (1<<13);
        AT91C_BASE_PIOB->PIO_CODR = (1<<26);
    blink = 1;
    }
    /*
    status = AT91C_BASE_AIC->AIC_IVR;
    if (status!=0x1124)
        AT91C_BASE_AIC->AIC_IVR = 0;
    
    status = AT91C_BASE_US0->US_CSR;
    if (status==0x1124)
        AT91C_BASE_AIC->AIC_IVR = 0;
*/
    AT91C_BASE_AIC->AIC_ICCR  = 1 << AT91C_ID_US0;                     /* Clear the  interrupts                            */
    AT91C_BASE_AIC->AIC_EOICR = 0;                                      /* Signal end of interrupt                              */
    
    return;    
}

Enable PIT ISR :
Код
AT91C_BASE_PITC->PITC_PIMR =  ((BSP_CPU_ClkFreq() * 1000) / 16 / OS_TICKS_PER_SEC) - 1;


  // Enable interrupts
  // Disable the interrupt on the interrupt controller
  AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_SYS);

  // Save the interrupt handler routine pointer and the interrupt priority
  void * ptr  = 0;
  ptr = (void *)(unsigned long)AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS];
  *(unsigned long *)&old_handler = (unsigned long)ptr;
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (unsigned long) pitc_handler;
  // Store the Source Mode Register
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
  // Clear the interrupt on the interrupt controller
  AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_SYS);

  // Enable the interrupt on the interrupt controller
  AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_SYS);

  // Enable the interrupt on the pit
  pimr = AT91C_BASE_PITC->PITC_PIMR;
  AT91C_BASE_PITC->PITC_PIMR = pimr | AT91C_PITC_PITIEN;

  // Enable the pit
  pimr = AT91C_BASE_PITC->PITC_PIMR;
  AT91C_BASE_PITC->PITC_PIMR = pimr | AT91C_PITC_PITEN;


}


PIT ISR :

Код
void pitc_handler(void)
{

for(unsigned short i=0; i<MAX_TIME_COUNTERS; i++)
    {
        if(gMeters[i].connected)
            {
             gMeters[i].counter += OS_TIMER_PERIOD * 2;
            
            // here some like "garbage collector"
            // if no reset within 5 minutes, disconnect that
            if (gMeters[i].counter > 300000)
                gMeters[i].connected = 0;
            }// ?connected
    }// loop

    old_handler();

}



sad.gif хоть не код, ткните хотя бы в страницу мануала ! мозги кипятЪ ! cranky.gif
Go to the top of the page
 
+Quote Post
AlexBoy
сообщение Mar 6 2007, 13:26
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394



По функциям, то что нужно добавить:
InitUSART:
1. Уарт должен быть настроен (тактовая, pio, скорость)
2. Разрешить прием/передачу AT91C_BASE_US0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
3. Включить прерывания в usart AT91C_BASE_US0->US_IER = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE | AT91C_US_FRAME;

USART0_ISR_Handler:
1. Статус должен быть прочитан обязательно. status = AT91C_BASE_US0->US_CSR;
2. Это убрать. AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_US0;
3. Сбросить флаги. AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;

Enable PIT ISR: все нормально

pitc_handler: что-то сильно наворочено, у меня попроще и обязательно нужно прочитать статус иначе не сбросятся прерывания
// ------------------------------------------------------------------------------
// Обработчик системного прерывания (ID_SYS=1)
void SYSIRQ_Handler(void)
{
DWORD status;

status = *AT91C_PITC_PIVR;
if (status & AT91C_PITC_PICNT) // Если системное прерывание от PIT таймера то вызвать OSTimeTick
{
OSTimeTick();
}
}
Go to the top of the page
 
+Quote Post
_dem
сообщение Mar 7 2007, 12:13
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



оно все так и сделано, а OSTick() вызывается в старом обработчике таймера.
мой таймер работает беспроблемно, и переключения тасков происходят, все гуд

а обработчик уарта - нет, хотя тот же код без оськи работает отлично
Go to the top of the page
 
+Quote Post
_dem
сообщение Mar 14 2007, 10:16
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



проблема решена радикально - переходом на FreeRTOS.

Спасибо за помощь cheers.gif
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Apr 3 2007, 07:55
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Такой вопрос назрел. А кто как "дебажится" в прерываниях?

Есть связка, EWARM 4.41a -> plugins ( C-Spy + uCOS ) -> AT91SAM7Sxxx. Вертится под Мюкосом, разумеется. Если открыть в дебаге окно "Registers" и выбрать AIC, то для отображения состояния регистров AIC их, очевидно, надо прочитать. А проблема в том, что однократное чтение того же AIC_IVR изменяет состояние AIC.

Я вообще-то вслепую отлаживаюсь, но осадочек имеется. (с) Хочется "поцивильнее". :)

Теоретически, uCOS работает в SVC-mode, в который переключается и при обработке преррываний тоже. А при чтении AIC_IVR в SVC-mode, Атмел говорит что всё произойдёт "without performing the associated automatic operations". У меня же отладчик постоянно показывает хрень, в виде указателя на "spurios vector". :(
Go to the top of the page
 
+Quote Post
_dem
сообщение Apr 3 2007, 09:21
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



Цитата(Tahoe @ Apr 3 2007, 08:55) *
Такой вопрос назрел. А кто как "дебажится" в прерываниях?

....


Да вроде бы все нормально дебажится...

Хотя сам тоже еще с AVR-а и MSP привык отлаживаться вслепую, но никаких проблем при отладке в прерываниях не было. (sam7 + IAR + SEGGER j-link). Дебаггер читает регистры AIC через логику JTAG-машины, и, как и пишет Атмел, при этом биты не обнуляются. Ни для AIC, ни для того же таймера (PITC) - биты обнуляются только кодом, а дебаггер все исправно показывает.
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Apr 3 2007, 12:28
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Можно еще protected mode использовать для AIC... smile.gif


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 3 2007, 12:28
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Tahoe @ Apr 3 2007, 06:55) *
А проблема в том, что однократное чтение того же AIC_IVR изменяет состояние AIC.
Залезть в .ddf и исключить IVR из списка отображаемых регистров.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Apr 3 2007, 14:27
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата
Можно еще protected mode использовать для AIC...

Ну дык uCOS из SVC и не вылезает. wink.gif За исключением собсно прерывания, но сам хендлер всё равно запускается в SVC. Вот потому-то мне и непонятно. Вроде всё по науке, запись в AIC_IVR производится...


Насчёт залезть в ddf была мысля. Под uCOS в принципе прокатит, потому как значение AIC_IVR там сначала переменной присваивается. Её и можно будет смотреть ( что сечйчас и делаю smile.gif ). Но как быть, если проект без ОСи? Если значение AIC_IVR используется непосредственно, как указатель на хендлер? Хотя, наверное, можно и пережить. smile.gif

2 _dem
А с чем связан прыжок обратно, с FreeRTOS на uCOS? Если не секрет? wink.gif
Go to the top of the page
 
+Quote Post

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

 


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


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