Файл <
avr
/
sfr
_
defs
.
h
>
включен во
все <
avr
/
ioXXXX
.
h
>
файлы,
которые
используют
макрос,
определенный
здесь, чтобы
заставить
регистр
специального
назначения
напомнить C
переменные
или простые
константы, в
зависимости от
_
SFR
_
ASM
_
COMPAT
define.
Некоторые примеры <avr/iocanxx.h> для того, чтобы показывать, как определить такой макрос:
#define PORTA _SFR_IO8(0x02)
#define EEAR _SFR_IO16(0x21)
#define UDR0 _SFR_MEM8(0xC6)
#define TCNT3 _SFR_MEM16(0x94)
#define CANIDT _SFR_MEM32(0xF0)
Если
_
SFR
_
ASM
_
COMPAT
не определен,
программы C могут
использовать
имена
подобные PORTA непосредственно
в выражениях C (также
на левой
стороне
операторов
назначения) и
GCC сделает
правильную
вещь
(короткое
использование
инструкции
ввода /
вывода, если
возможно).
Определение__ SFR_OFFSET в
этом случае
не
используется.
Определение
_
SFR
_
ASM
_
COMPAT
заставляет
эти имена
работать как
простые
константы
(адреса
регистраторов
ввода / вывода).
Это является необходимым
когда
включено в предобработанный
ассемблер (*.S)
исходные
файлы, так
что это
сделано
автоматически
if __
ASSEMBLER
__
is определенный.
По умолчанию,
все адреса
определены,
как будто они
были
адресами
памяти (используемый
в lds/c-
инструкции).
Использовать
эти адреса в
инструкциях ввода/вывода
,
вы должны
вычесть из них 0x20.
Для большей обратной совместимостьи, вставьте следующее в начале вашего старого файла источника ассемблера:
#define __SFR_OFFSET 0
Это
автоматически
вычитает 0x20 от
пространственных
адресов
ввода - вывода,
но это
взломает, так
что
рекомендуют
изменить ваш
источник: перенесите
по словам
такие адреса
в макросе,
определенном
здесь, как
показано
ниже. После
того, как это
сделано, __
SFR
_
OFFSET
определение
больше не
нужно, и
может быть удалено.
Реальный пример - этот код может использоваться в загрузчике, который является переносным между устройствами с SPMCR в разных адресах.
#if _SFR_IO_REG_P(SPMCR)
out _SFR_IO_ADDR(SPMCR), r24
#else
sts _SFR_MEM_ADDR(SPMCR), r24
#endif
Вы
можете
использовать
команды in
/
out
/
cbi
/
sbi
/
sbic
/
sbis
,
без _
SFR
_
IO
_
REG
_
P
test,
если вы
знаете, что
регистр
находится в
пространстве
ввода -
вывода (как
например с SREG,). Если это -
не, ассемблер
будет
жаловаться
(Адрес ввода -
вывода из
диапазона 0...0x3f), так
что это
должно быть
довольно
безопасно.
Если
Вы не
определяете __
SFR
_
OFFSET
(так что это
будет 0x20 по
умолчанию),
все
специальные
адреса
регистра
определены
как адреса памяти
(так SREG 0x5f), и
(если размер
кода и
скорость не
важны, и Вы не
любите
уродливый #if выше) вы
можете
всегда
использовать
lds/sts, чтобы
обратиться к
ним. Но, это не
будет работать
если __
SFR
_
OFFSET
!= 0x20,
так
используйте
различную
макрокоманду
(определенный,
только если __
SFR
_
OFFSET
== 0x20) для
безопасности:
sts _SFR_ADDR(SPMCR), r24
В
программах C, все 3
комбинации
из _
SFR
_
ASM
_
COMPAT
and __
SFR
_
OFFSET
поддерживаются
- макрос _
SFR
_
ADDR
(
SPMCR
)
может
использоваться,
чтобы
получить адрес
регистра SPMCR (0x57
или 0x68
в
зависимости
от
устройства).