Spec-Zone.ru › GCC 7

6.16 Пространства имён адресов

В качестве расширения GNU C поддерживает пространства имён адресов, определённые в проекте N1275 черновика ISO/IEC DTR 18037. Поддержка пространств имён адресов в GCC будет развиваться по мере изменения черновика технического отчета. Способы вызова для любого целевого процессора также могут измениться. В настоящее время только целевые процессоры AVR, SPU, M32C, RL78 и x86 поддерживают пространства адресов, отличные от универсального пространства адресов.

Идентификаторы пространства адресов могут быть использованы точно так же, как и любой другой квалификатор типа C (например, const или volatile). Дополнительные сведения см. в документе N1275.

6.16.1 Пространства имён адресов AVR

В целевом процессоре AVR есть несколько пространств адресов, которые можно использовать для размещения только для чтения данных в памяти флэш-памяти и доступа к этим данным с помощью специальных инструкций LPM или ELPM, необходимых для чтения из флэш-памяти.

По умолчанию все данные, включая данные только для чтения, находятся в ОЗУ (универсальное пространство адресов), поэтому для размещения данных только для чтения в памяти флэш-памяти и для генерации правильных инструкций доступа к этим данным без использования (встраиваемого) ассемблерного кода необходимы пространства адресов, отличные от универсального.

__flash

Квалификатор __flash размещает данные в секции .progmem.data. Данные считываются с помощью инструкции LPM. Указатели на это пространство адресов имеют ширину 16 бит.

__flash1
__flash2
__flash3
__flash4
__flash5

Это 16-битные пространства адресов, размещающие данные в секции .progmemN.data, где N относится к пространству адресов __flashN. Компилятор устанавливает сегментный регистр RAMPZ соответствующим образом перед считыванием данных с помощью инструкции ELPM.

__memx

Это 24-битное пространство адресов, которое линейно отображает флэш-память и ОЗУ: если старший бит адреса установлен, данные считываются из ОЗУ, используя два младших байта в качестве адреса ОЗУ. Если старший бит адреса сброшен, данные считываются из флэш-памяти с RAMPZ установленным в соответствии со старшим байтом адреса. См. __builtin_avr_flash_segment.

Объекты в этом пространстве адресов размещаются в .progmemx.data.

Пример

char my_read (const __flash char ** p)
{
    /* p is a pointer to RAM that points to a pointer to flash.
       The first indirection of p reads that flash pointer
       from RAM and the second indirection reads a char from this
       flash address.  */

    return **p;
}

/* Locate array[] in flash memory */
const __flash int array[] = { 3, 5, 7, 11, 13, 17, 19 };

int i = 1;

int main (void)
{
   /* Return 17 by reading from flash memory */
   return array[array[i]];
}

Для каждого пространства имён адресов, поддерживаемого avr-gcc, определена одноимённая, но заглавная встроенная макрокоманда. Цель состоит в облегчении проверки наличия поддержки соответствующего пространства адресов:

#ifdef __FLASH
const __flash int var = 1;

int read_var (void)
{
    return var;
}
#else
#include <avr/pgmspace.h> /* From AVR-LibC */

const int var PROGMEM = 1;

int read_var (void)
{
    return (int) pgm_read_word (&var);
}
#endif /* __FLASH */

Обратите внимание, что атрибут progmem размещает данные в флэш-памяти, но доступ к этим данным читается из универсального пространства адресов, т. е. из ОЗУ, поэтому вам потребуются специальные средства доступа, такие как pgm_read_byte из AVR-LibC вместе с атрибутом progmem.

Ограничения и замечания

  • Чтение через границу сегмента 64 Кбайт пространств адресов __flash или __flashN демонстрирует неопределённое поведение. Единственное пространство адресов, поддерживающее чтение через границы сегментов флэш-памяти 64 Кбайт, — __memx.
  • При использовании одного из пространств адресов __flashN необходимо настроить скрипт компоновщика для размещения секций .progmemN.data в соответствии с вашими потребностями.
  • Все данные или указатели на пространства адресов, отличные от универсальных, должны быть квалифицированы как const, т. е. как данные только для чтения. Это всё ещё относится, если данные в одном из этих пространств адресов, например, номер версии программного обеспечения или справочная таблица калибровки, предназначены для изменения после загрузки, скажем, загрузчиком. В этом случае правильной квалификацией является const volatile, чтобы компилятор не оптимизировал известные значения или не вставлял их как непосредственные значения в операнды инструкций.
  • Следующий код инициализирует переменную pfoo, расположенную в статическом хранилище, 24-битным адресом:
    extern const __memx char foo;
    const __memx void *pfoo = &foo;

    Для этого кода требуется как минимум binutils 2.23, см. PR13503.

  • Для упрощённых устройств Tiny, таких как ATtiny40, пространства адресов не поддерживаются. Данные можно разместить в памяти флэш-памяти и читать их с помощью атрибута progmem, см. Атрибуты переменных AVR.

6.16.2 Пространства имён адресов M32C

В целевом процессоре M32C, с вариантами процессоров R8C и M16C, переменные, квалифицированные как __far , доступны с помощью 32-битных адресов для доступа к памяти за пределами первых 64 Кбайт. Если __far используется с вариантами процессоров M32CM или M32C, он не имеет никакого эффекта.

6.16.3 Пространства имён адресов RL78

В целевом процессоре RL78 переменные, квалифицированные как __far , доступны с помощью 32-битных указателей (20-битных адресов), а не стандартных 16-битных адресов. Переменные, не являющиеся far, предполагаются расположенными в верхней части 64 Кбайт пространства адресов.

6.16.4 Пространства имён адресов SPU

В целевом процессоре SPU переменные могут быть объявлены как принадлежащие другому пространству адресов, квалифицировав тип идентификатором пространства адресов __ea.

extern int __ea i;

Компилятор генерирует специальный код для доступа к переменной i. Он может использовать поддержку библиотеки выполнения или генерировать специальные машинные инструкции для доступа к этому пространству адресов.

6.16.5 Пространства имён адресов x86

В целевом процессоре x86 переменные могут быть объявлены как относительные к сегментам %fs или %gs.

__seg_fs
__seg_gs

Объект доступен с соответствующим префиксом переопределения сегмента.

Соответствующая база сегмента должна быть установлена каким-либо методом, специфичным для операционной системы. Вместо необходимости в дорогостоящей системной вызове для получения базы сегмента, эти пространства адресов не считаются подпространствами универсального (плоского) пространства адресов. Это означает, что для преобразования указателей между этими пространствами адресов и универсальным пространством адресов требуется явное приведение типов. На практике приложение должно преобразовать к uintptr_t и применить смещение базы сегмента, которое оно установило ранее.

Макросы препроцессора __SEG_FS и __SEG_GS определены, когда эти пространства адресов поддерживаются.

Далее: Длина ноль, Предыдущее: Фиксированная точка, Вверх: Расширения C [Содержание][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/Named-Address-Spaces.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API