Spec-Zone.ru › GCC 4

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

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

Идентификаторы пространств адресов могут использоваться точно так же, как и любой другой квалификатор типа 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.

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

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

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

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

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

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

extern int __ea i;

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

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

Spec-Zone.ru

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