Для встроенных приложений часто требуется доступ к ячейкам фиксированной памяти для периферийных регистров. Стандартный способ, который я нашел для этого, выглядит примерно так:
// access register 'foo_reg', which is located at address 0x100
#define foo_reg *(int *)0x100
foo_reg = 1; // write to foo_reg
int x = foo_reg; // read from foo_reg
Я понимаю, как это работает, но я не понимаю, как распределяется пространство для foo_reg (т.е. что удерживает компоновщик от размещения другой переменной в 0x100?). Может ли пространство зарезервировано на уровне C, или же должна быть опция компоновщика, которая указывает, что ничего не должно быть расположено на 0x100. Я использую инструменты GNU (gcc, ld и т.д.), Поэтому меня в основном интересует специфика этого набора инструментов на данный момент.
Некоторая дополнительная информация о моей архитектуре, чтобы прояснить вопрос:
Мой процессор взаимодействует с FPGA через набор регистров, отображаемых в обычное пространство данных (где живут переменные) процессора. Поэтому мне нужно указать на эти регистры и заблокировать связанное адресное пространство. Раньше я использовал компилятор с расширением для определения переменных из C-кода. Я бы сгруппировал регистры в структуру, а затем разместил структуру в соответствующем месте:
typedef struct
{
BYTE reg1;
BYTE reg2;
...
} Registers;
Registers regs _at_ 0x100;
regs.reg1 = 0;
Фактически создание структуры "Регистры" резервирует пространство в глазах компилятора/компоновщика.
Теперь, используя инструменты GNU, я, очевидно, не имею расширения. Использование метода указателя:
#define reg1 *(BYTE*)0x100;
#define reg2 *(BYTE*)0x101;
reg1 = 0
// or
#define regs *(Registers*)0x100
regs->reg1 = 0;
Это простое приложение без ОС и без расширенного управления памятью. По существу:
void main()
{
while(1){
do_stuff();
}
}