Я часто пишу так называемые выводы ввода / вывода памяти, подобные этому
P3OUT |= BIT1;
Я предположил, что P3OUT заменяют что-то вроде этого моим препроцессором:
*((unsigned short *) 0x0222u)
Но сегодня я ворвался в файл H и увидел что-то в этом роде:
volatile unsigned short P3OUT @ 0x0222u;
До этого происходит еще некоторое расширение, но, как правило, это происходит. Используется символ «@». Выше того, что есть некоторые # прагмы об использовании расширенного набора языка C. Я предполагаю, что это какая-то директива для компоновщика, и фактически символ определяется как находящийся в этом месте на карте памяти.
Было ли мое предположение правильным, что происходит в большинстве случаев у большинства компиляторов? Имеет ли это значение так или иначе? Откуда взялось это обозначение @, это какой-то стандарт?
Я использую IAR Embedded workbench.
Этот вопрос аналогичен этому: как поместить переменную в данный абсолютный адрес в памяти (с GCC) . Это соответствует тому, что я предполагал, что мой компилятор все равно.
Хотя выражение типа (unsigned char *)0x1234
на многих компиляторах дает указатель на аппаратный адрес 0x1234, ничто в стандарте не требует какой-либо конкретной связи между целым числом, которое передается указателю и результирующему адресу. Единственное, что специфицирует стандарт, это то, что если конкретный целочисленный тип не меньше, чем intptr_t
, и приведение указателя к этому конкретному типу дает некоторое значение, то приведение этого конкретного значения обратно к исходному типу указателя даст эквивалент указателя к оригиналу.
Компилятор IAR предлагает нестандартное расширение, которое позволяет компилятору запрашивать, чтобы переменные размещались по указанным жестко закодированным адресам. Это дает некоторые преимущества по сравнению с использованием макросов для создания выражений указателя. Во-первых, это гарантирует, что такие переменные будут синтаксически рассматриваться как переменные; в то время как выражения pointer-kludge обычно интерпретируются правильно, если они используются в законном коде, возможно, для нелегитимного кода, который должен завершиться ошибкой компиляции, чтобы скомпилировать, но произвести нечто иное, чем желаемый эффект. Кроме того, синтаксис IAR определяет символы, доступные для компоновщика, и поэтому может использоваться в модулях на языке сборки. Напротив, файл .H, который определяет macros указателя-kludge, не будет использоваться в модуле на языке ассемблера; любое оборудование, которое будет использоваться как в коде C, так и в сборе, должно указывать адрес в двух отдельных местах.
Короткий ответ на вопрос в вашем названии «по-разному». Хуже всего то, что компиляторы от разных поставщиков для одного и того же целевого процессора будут использовать разные подходы. Вот этот
volatile unsigned short P3OUT @ 0x0222u;
Является распространенным способом размещения переменной по фиксированному адресу. Но вы также увидите, что он используется для идентификации отдельных битов в ячейке с отображением памяти = особенно для микроcontrollerов, которые имеют битовые инструкции, такие как семейства ПОС.
Это те вещи, которые C-стандарт не адресует, и должен IMHO, поскольку небольшие встроенные микроcontrollerы в конечном итоге станут основным рынком для C (да, я знаю, что kernel написано на C, но много материала для пользовательского пространства переход на C ++).
Я фактически присоединился к комитету С, чтобы попытаться двигаться в этом направлении, но мое спонсорство ушло, и это очень дорогое увлечение.
Аналогичная область объявляет функцию ISR.
В этом документе показан один из подходов, которые мы рассмотрели