Spec-Zone.ru › GCC 6

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

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

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

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

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

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

__flash

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

__flash1
__flash2
__flash3
__flash4
__flash5

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

__memx

Это 24-битное пространство имён, которое линейно отображает память flash и ОЗУ: Если старший бит адреса установлен, данные считываются из ОЗУ, используя два младших байта в качестве адреса ОЗУ. Если старший бит адреса сброшен, данные считываются из памяти flash с 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 размещает данные в памяти flash, но доступ к этим данным читается из общего пространства имён, то есть из ОЗУ, поэтому вам нужны специальные средства доступа, такие как pgm_read_byte из AVR-LibC вместе с атрибутом progmem.

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

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

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

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-6.5.0/gcc/Named-Address-Spaces.html

Spec-Zone.ru

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