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

 
 
 
Reply to this topicStart new topic
> Использование portENTER_CRITICAL(), Программирование для FreeRTOS
Cryon
сообщение Nov 18 2008, 19:02
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 28-02-06
Пользователь №: 14 797



Доброго времени суток!

Есть пример функции, которая посылает байт (см. ниже), используя очередь под FreeRTOS. Если ее упростить до уровня моего вопроса, то останется вот это:

portENTER_CRITICAL ();
xQueueSend (xTX0Queue, &cOutChar, xBlockTime);
portEXIT_CRITICAL ();

Внимание вопрос: portENTER_CRITICAL () запрещает прерывания в текущем режиме, причем как IRQ, так и FIQ. Тогда как же так получается, что отрабатывает xBlockTime (т.е. прерывания от таймера должны быть) в xQueueSend() ? wacko.gif

Спасибо!

Сами функции:

Код
signed portBASE_TYPE uart0PutChar (signed portCHAR cOutChar, portTickType xBlockTime)
{
  signed portBASE_TYPE xReturn = 0;

  portENTER_CRITICAL ();
  {
    //
    //  Is there space to write directly to the UART?
    //
    if (*plTHREEmpty0 == (portLONG) pdTRUE)
    {
      *plTHREEmpty0 = pdFALSE;
      UART0_THR = cOutChar;
      xReturn = pdPASS;
    }
    else
    {
      //
      //  We cannot write directly to the UART, so queue the character.  Block for a maximum of
      //  xBlockTime if there is no space in the queue.
      //
      xReturn = xQueueSend (xTX0Queue, &cOutChar, xBlockTime);

      //
      //  Depending on queue sizing and task prioritisation:  While we were blocked waiting to post
      //  interrupts were not disabled.  It is possible that the serial ISR has emptied the Tx queue,
      //  in which case we need to start the Tx off again.
      //
      if ((*plTHREEmpty0 == (portLONG) pdTRUE) && (xReturn == pdPASS))
      {
        xQueueReceive (xTX0Queue, &cOutChar, serNO_BLOCK);
        *plTHREEmpty0 = pdFALSE;
        UART0_THR = cOutChar;
      }
    }
  }

  portEXIT_CRITICAL ();

  return xReturn;
}


portENTER_CRITICAL() продифайнен так:
#define portENTER_CRITICAL() vPortEnterCritical();

Код
void vPortEnterCritical( void )
{
    /* Disable interrupts as per portDISABLE_INTERRUPTS();                             */
    asm volatile (
        "STMDB    SP!, {R0}            \n\t"    /* Push R0.                                */
        "MRS    R0, CPSR            \n\t"    /* Get CPSR.                            */
        "ORR    R0, R0, #0xC0        \n\t"    /* Disable IRQ, FIQ.                    */
        "MSR    CPSR, R0            \n\t"    /* Write back modified value.            */
        "LDMIA    SP!, {R0}" );                /* Pop R0.                                */

    /* Now interrupts are disabled ulCriticalNesting can be accessed
    directly.  Increment ulCriticalNesting to keep a count of how many times
    portENTER_CRITICAL() has been called. */
    ulCriticalNesting++;
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 18 2008, 22:12
Сообщение #2


Гуру
******

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



Цитата(Cryon @ Nov 18 2008, 21:02) *
Внимание вопрос: portENTER_CRITICAL () запрещает прерывания в текущем режиме, причем как IRQ, так и FIQ. Тогда как же так получается, что отрабатывает xBlockTime (т.е. прерывания от таймера должны быть) в xQueueSend() ? wacko.gif
Если я помню правильно, то при необходимости использовать xBlockTime (т.е. когда очередь полна) происходит перепланировка. Управление передается другому процесу, у которого прерывания разрешены.


--------------------
На любой вопрос даю любой ответ
"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
Cryon
сообщение Nov 20 2008, 15:21
Сообщение #3





Группа: Новичок
Сообщений: 9
Регистрация: 28-02-06
Пользователь №: 14 797



Цитата(Сергей Борщ @ Nov 19 2008, 01:12) *
Если я помню правильно, то при необходимости использовать xBlockTime (т.е. когда очередь полна) происходит перепланировка. Управление передается другому процесу, у которого прерывания разрешены.


Да, спасибо! Похоже, так все и есть. Почитал еще форумов, порылся в коде.

Когда xBlockTime в действии задачи будут суспендиться и восстанавливаться циклически, соответственно vTaskSuspendAll() и xTaskResumeAll(). И как я понял вот как раз последняя из них передает управление задаче с более высоким приоритетом, чем текущаяя посредством taskYIELD().
yeah.gif
Тем не менее, допустим, что нет задачи с большим приоритетом и текущая задача остается активной в режиме ожидания xBlockTime. Тогда получается, что будут утеряны все тики таймера, возникшие во время xBlockTime. В этом случае вышеприведенная функция посылки данных через очередь в критической секции, не самое хорошее решение, т.к. пагубно влияет на время отклика ОС.

И всетаки это была демо функция и свою роль она сыграла правильно smile.gif

Шаблон для таймаута в xQueueGenericSend:

Код
if( xTicksToWait > ( portTickType ) 0 )
{
    vTaskSuspendAll();

    if( prvIsQueueFull( pxQueue ) )
    {
        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
        {
            if( !xTaskResumeAll() )
            {
                taskYIELD();
            }
        }
        else
        {
            ( void ) xTaskResumeAll();
        }
    }
    else
    {
        ( void ) xTaskResumeAll();
    }
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 20 2008, 16:29
Сообщение #4


Гуру
******

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



Цитата(Cryon @ Nov 20 2008, 17:21) *
Тем не менее, допустим, что нет задачи с большим приоритетом и текущая задача остается активной в режиме ожидания xBlockTime.
Всегда есть такая задача. Это IdleTask (ну или созвучное название). А вот если вы решили подождать в IdleTask - то против лома ни одна лесопилка не устоит.


--------------------
На любой вопрос даю любой ответ
"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

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

 


RSS Текстовая версия Сейчас: 17th June 2025 - 18:58
Рейтинг@Mail.ru


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