You are here

Сопрограммы: ограничения

Перевод может содержать ошибки. Читайте первоисточник: Co-Routine Limitations and Restrictions

Назад: [Сопрограммы во FreeRTOS] Вверх: [Сопрограммы во FreeRTOS] Вперёд: [Сопрограммы во FreeRTOS]

 

Преимуществом использования сопрограмм является меньшее требуемое количество ОЗУ по сравнению с эквивалентным решением, использующим задачи. Но достигается это за счёт некоторых ограничений на использование сопрограмм. Сопрограммы более ограничены и сложнее в использовании по сравнению с использованием задач.

  • Совместное использование стека

    Стек сопрограммы не поддерживается, когда сопрограмма блокируется. Это означает, что переменные, расположенные в стеке, скорее всего потеряют свои значения. Чтобы преодолеть это, переменная, которая должна поддерживать своё значение во время блокирующего вызова, должна объявляться как статическая. Например:

    /*----------------------------------------------------------------------------*/
    void vACoRoutineFunction( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
    {
    static char c = 'a';
    
        /* Сопрограмма должна начинаться с вызова макроса crSTART(). */
        crSTART( xHandle );
    
        for( ;; )
        {
            /* Если здесь мы зададим переменной c значение 'b'. */
            c = 'b';
    
            /* Затем выполним блокирующий вызов. */
            crDELAY( xHandle, 10 );
    
            /* В этом месте переменная c будет гарантированно по прежнему иметь */
            /* значение 'b', только если она была объявлена статической,
            /* как в этом примере. */
        }
    
        /* Сопрограмма должна завершаться вызовом макроса crEND(). */
        crEND();
    }
    
    

    Другим следствием совместного использования стека является то, что вызовы функций API, которые могут вызвать блокировку сопрограммы, могут быть сделаны только из самой функции сопрограммы, но не из функции, вызываемой сопрограммой. Например:

    /*----------------------------------------------------------------------------*/
    void vACoRoutineFunction( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
    {
        /* Сопрограмма должна начинаться с вызова макроса crSTART(). */
        crSTART( xHandle );
    
        for( ;; )
        {
            /* Здесь можно вызывать блокирующую функцию. */
            crDELAY( xHandle, 10 );
    
            /* Но блокирующий вызов нельзя делать из функции vACalledFunction(). */
            vACalledFunction();
        }
    
        /* Сопрограмма должна завершаться вызовом макроса crEND(). */
        crEND();
    }
    
    void vACalledFunction( void )
    {
        /* Здесь нелья делать блокирующие вызовы! */
    }
    
    
  • Использование операторов switch

    Реализация сопрограмм по-умолчанию, включённая в поставку FreeRTOS, не позволяет выполнять блокирующие вызовы из оператора switch. Для примера:

    /*----------------------------------------------------------------------------*/
    void vACoRoutineFunction( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
    {
        /* Сопрограмма должна начинаться с вызова макроса crSTART(). */
        crSTART( xHandle );
    
        for( ;; )
        {
            /* Здесь можно делать блокирующие вызовы. */
            crDELAY( xHandle, 10 );
    
            switch( aVariable )
            {
            case 1 : /* А здесь блокирующие вызовы делать нельзя! */
                break;
            default: /* И здесь тоже нельзя. */
            }
        }
    
        /* Сопрограмма должна завершаться вызовом макроса crEND(). */
        crEND();
    }
    
    

 

Hobby's category: