Spec-Zone.ru › GCC 14

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

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

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

  • Пространства имён адресов AVR
  • Пространства имён адресов M32C
  • Пространства имён адресов PRU
  • Пространства имён адресов RL78
  • Пространства имён адресов x86

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

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

Устройства, принадлежащие к avrtiny и avrxmega3, могут обращаться к памяти flash с помощью инструкций LD*, поскольку память flash отображается в адресное пространство RAM. Не требуется расширений языка, таких как __flash или атрибут progmem. Файлы описания связующего модуля по умолчанию для этих устройств учитывают эту функцию, и .rodata остаётся в памяти flash: Компилятор просто генерирует инструкции LD*, а скрипт связующего модуля добавляет специфичные для ядра смещения ко всем символам .rodata: 0x4000 в случае avrtiny и 0x8000 в случае avrxmega3. Список соответствующих устройств см. в разделе Параметры AVR.

Для устройств, не относящихся к avrtiny или avrxmega3, все данные, включая данные только для чтения, находятся в памяти RAM (общее адресное пространство), потому что память flash не отображается в адресном пространстве RAM. Для размещения данных только для чтения в памяти flash и генерации правильных инструкций для доступа к этим данным без использования (встроенного) кода ассемблера необходимы специальные адресные пространства.

__flash

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

__flash1
__flash2
__flash3
__flash4
__flash5

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

__memx

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

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

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

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

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

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

На целевом устройстве PRU, переменные, квалифицированные с помощью __regio_symbol являются псевдонимами, используемыми для доступа к специальным регистрам ввода/вывода процессора. Они должны быть объявлены как extern, потому что такие переменные не будут выделены в любой памяти данных. Они также должны быть помечены как volatile, и могут быть только 32-битными целочисленными типами. Единственными именами, которые могут иметь эти переменные, являются __R30 и __R31, представляющие соответственно R30 и R31 специальные регистры ввода/вывода процессора. Следовательно, следующий пример является единственным допустимым использованием __regio_symbol:

extern volatile __regio_symbol uint32_t __R30;
extern volatile __regio_symbol uint32_t __R31;

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

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

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

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

__seg_fs
__seg_gs

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

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

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

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

Spec-Zone.ru

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