Домашняя страница библиотеки_c AVR

Синтаксис языка C

Библиотека языка C GNU glibc

 Страницы развития библиотеки_с AVR

Главная страница

Инструкция пользователя

Содержание библиотеки_c

Часто задаваемые вопросы

Содержание по алфавиту

Демонстрационные проекты


Дополнительные примечания к <avr/sfr_defs.h>

<avr/sfr_defs.h>: Регистр специального назначения

Файл <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 в разных адресах.

<avr/iom163.h>: #define SPMCR _SFR_IO8(0x37)
<avr/iom128.h>: #define SPMCR _SFR_MEM8(0x68)
#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 в зависимости от устройства).

Hosted by uCoz