You are here

GCC Naked Attribute

Перевод может содержать ошибки. Читайте первоисточник: GCC Naked Attribute

Назад: [Как работает FreeRTOS] Вверх: [Как работает FreeRTOS] Вперёд: [Как работает FreeRTOS]

 

В предыдущем разделе было показано, как атрибут 'signal' используется при реализации обработчика прерывания на языке C, и как это приводит к автоматическому сохранению части контекста (сохраняются только регистры процессора, используемые обработчиком прерывания). Однако для того, чтобы выполнить переключение, необходимо сохранить весь контекст полностью.

Код приложения может явно сохранять все регистры процессора при входе в обработчик прерывания, но это приведёт к двухкратному сохранению некоторых регистров процессора - один раз кодом, сгенерированным компилятором, а второй раз - кодом приложения. Это нежелательно, и чтобы избежать такой ситуации, используется атрибут 'naked' в дополнение к атрибуту 'signal', как в примере ниже:

/*----------------------------------------------------------------------------*/
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );

void SIG_OUTPUT_COMPARE1A( void )
{
    /* Код обработчика прерывания на языке C для тиков ОС. */
    vPortYieldFromTick();
}

Атрибут 'naked'  запрещает компилятору генерировать какой-либо код входа и выхода из функцию. Теперь ассемблерный листинг будет выглядеть намного проще:
;-------------------------------------------------------------------------------
;void SIG_OUTPUT_COMPARE1A( void )
;{
    ; ---------------------------------------
    ; КОМПИЛЯТОР НЕ ГЕНЕРИРУЕТ ЗДЕСЬ НИКАКОГО
    ; КОДА ДЛЯ СОХРАНЕНИЯ РЕГИСТРОВ, КОТОРЫЕ
    ; БУДУТ ИЗМЕНЕНЫ В ОБРАБОТЧИКЕ ПРЕРЫВАНИЯ.
    ; ---------------------------------------

    ; КОД, СГЕНЕРИРОВАННЫЙ КОМПИЛЯТОРОМ ИЗ
    ; КОДА ПРИЛОЖЕНИЯ НА ЯЗЫКЕ C.

    ;vTaskIncrementTick();
    CALL    0x0000029B       ;Call subroutine

    ; ---------------------------------------

    ; КОМПИЛЯТОР НЕ ГЕНЕРИРУЕТ ЗДЕСЬ НИКАКОГО
    ; КОДА ДЛЯ ВОССТАНОВЛЕНИЯ РЕГИСТРОВ ПРИ
    ; ВЫХОДЕ ИЗ ОБРАБОТЧИКА ПРЕРЫВАНИЯ.
    ; ---------------------------------------
;}

Когда используется атрибут naked', компилятор не генерирует никакого кода входа или выхода из функции. Поэтому теперь нужно этот код добавлять явно. Макросы FreeRTOS portSAVE_CONTEXT() и portRESTORE_CONTEXT() соответственно сохраняют и восстанавливают весь контекст выполнения:

/*----------------------------------------------------------------------------*/
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );

void SIG_OUTPUT_COMPARE1A( void )
{
    /* Макрос, который явно сохраняет весь контекст выполнения. */
    portSAVE_CONTEXT();

    /* Код обработчика прерывания тиков ОС на языке C. */
    vPortYieldFromTick();

    /* Макрос, который явно восстанавливает весь контекст выполнения. */
    portRESTORE_CONTEXT();

    /* Команда возврата из прерывания также должна быть добавлена явно. */
    asm volatile ( "reti" );
}

Атрибут 'naked' даёт коду приложения полный контроль на тем, как и когда сохраняется контекст выполнения (в рассматриваемом примере это контекст для микроконтроллера AVR). Если код приложения сохраняет контекст при входе в обработчик прерывания, нет необходимости сохранять его снова перед переключением контекста, поэтому ни один из регистров процессора не сохраняется дважды.


Далее: Реализация FreeRTOS - код тика FreeRTOS

Hobby's category: