
- •Глава 1. Сведения о компиляторе
- •1.1.Введение
- •1.2. Основные вопросы
- •1.3. Описание компилятора и документация
- •1.4. Компилятор и другие средства разработки
- •1.5. Набор возможностей компилятора
- •1.5.1. Стандарт ANSI Си
- •1.5.2. Оптимизация
- •1.5.3. Поддержка стандартной ANSI библиотеки
- •1.5.4. Гибкие модели памяти
- •1.5.5. Драйвер компилятора
- •Глава 2. Отличия 16-битового компилятора от ANSI
- •2.1. Введение
- •2.2. Основные вопросы
- •2.3. Отличия ключевых слов
- •2.3.1. Определение атрибутов переменных
- •2.3.2. Определение атрибутов функций
- •2.3.3. Inline функции
- •2.3.4. Переменные в определенных регистрах
- •2.3.4.1. Определение глобальных регистровых переменных
- •2.3.4.2. Определение локальных регистровых переменных
- •2.3.5. Комплексные числа
- •2.3.6. Целые размером в двойное слово
- •2.3.7. Ссылки на тип с помощью typeof
- •2.4. Отличия операторов
- •2.4.1. Метки как значения
- •2.4.2. Условные операторы с опущенными операндами
- •2.4.3. Диапазоны case
- •2.5. Отличия выражений
- •2.5.1. Двоичные константы
- •Глава 3. Использование компилятора в командной строке
- •3.1. Введение
- •3.2. Основные вопросы
- •3.3. Обзор
- •3.4. Соглашение для имен файлов
- •3.5. Опции
- •3.5.1. Опции, специфические для устройств dsPIC
- •3.5.2. Опции для управления типом результатов
- •3.5.3. Опции для управления диалектом Cи
- •3.5.5. Опции для отладки
- •3.5.6. Опции для управления оптимизацией
- •3.5.7. Опции для управления препроцессором
- •3.5.8. Опции для ассемблера
- •3.5.9. Опции для компоновщика
- •3.5.10. Опции для поиска в каталогах
- •3.5.11. Опции для соглашений по генерации кода
- •3.6. Переменные окружения
- •3.7. Предопределенные имена макро
- •3.9. Компиляция нескольких файлов в командной строке
- •3.10. Особенные символы
- •Глава 4. Среда периода исполнения
- •4.1. Введение
- •4.2. Основные вопросы
- •4.3. Адресное пространство
- •4.4. Запуск и инициализация
- •4.5. Пространства памяти
- •4.6. Модели памяти
- •4.6.1. Ближние и дальние данные
- •4.6.2. Ближний и дальний код
- •4.7. Расположение кода и данных
- •4.8. Программный стек
- •4.9. Использование стека в Си
- •4.11. Соглашения по вызову функций
- •4.11.1. Параметры функции
- •4.11.2. Возвращаемое значение
- •4.12. Соглашения о регистрах
- •4.13. Двоичная инверсия и модульная адресация
- •4.14.1. Загрузочные и защищенные константы
- •4.14.2. Строковые константы как аргументы
- •4.14.3. Переменные с квалификатором const в безопасной Flash
- •4.14.4. Модель совместимости объектов
- •Глава 5. Типы данных
- •5.1. Введение
- •5.2. Основные вопросы
- •5.3. Представление данных
- •5.4. Целые
- •5.5. С плавающей точкой
- •5.6. Указатели
- •Глава 6. Дополнительные типы указателей Си
- •6.1. Введение
- •6.2. Управляющие PSV указатели
- •6.2.1. Определение данных для управления доступом PSV
- •6.2.2. Управляемый доступ PSV
- •6.2.3. Рассмотрение ISR
- •6.3. PMP указатели
- •6.3.1. Инициализация PMP
- •6.3.2. Объявление нового пространства памяти
- •6.3.3. Определение переменных в пространстве PMP
- •6.4. Внешние указатели
- •6.4.1. Объявление нового пространства памяти
- •6.4.2. Определение переменных во внешнем пространстве
- •6.4.3. Определение способа доступа к пространству памяти
- •6.4.3.2. Функции записи
- •6.4.4. Пример внешней памяти
- •Глава 7. Файлы поддержки устройства
- •7.1. Введение
- •7.2. Основные вопросы
- •7.3. Файлы заголовков процессора
- •7.4. Файлы определения регистров
- •7.5. Использование SFR
- •7.6. Использование макросов
- •7.6.1. Макросы настройки битов конфигурации
- •7.6.2. Макросы использования ассемблера inline
- •7.6.3. Макросы выделения памяти данных
- •7.6.4. Макросы объявления ISR
- •7.7. Адресация EEDATA из Си - только для dsPIC30F
- •7.7.1. Доступ к EEDATA через PSV
- •7.7.2. Доступ к EEDATA посредством команд TBLRDx
- •7.7.3. Дополнительные источники информации
- •Глава 8. Прерывания
- •8.1. Введение
- •8.2. Основные вопросы
- •8.3. Написание программы обработки прерывания
- •8.3.1. Рекомендации по написанию ISR
- •8.3.3. Кодирование ISR
- •8.3.4. Использование макросов для объявления простых ISR
- •8.4. Запись вектора прерывания
- •8.4.1. Вектора прерываний dsPIC30F (без SMPS)
- •8.4.3. Вектора прерываний PIC24F
- •8.4.4. Вектора прерываний dsPIC33F/PIC24H
- •8.5. Сохранение контекста в ISR
- •8.7. Вложенные прерывания
- •8.8. Разрешение/запрещение прерываний
- •8.9. Разделение памяти между основной программой и ISR
- •8.9.1. Разработка проблем
- •8.9.2. Разработка решений
- •8.9.3. Пример приложения
- •8.10. Использование PSV в ISR
- •Глава 9. Совместное использование ассемблера и Си
- •9.1. Введение
- •9.2. Основные вопросы
- •9.3. Смесь переменных и функций на ассемблере и Си
- •9.4. Использование ассемблера inline
- •Приложение A. Определяемое реализацией поведение
- •A.12. Квалификаторы
- •A.13. Деклараторы
- •A.14. Операторы
- •A.17. Сигналы
- •A.18. Потоки и файлы
- •A.20. Errno
- •A.22. Abort
- •A.23. Exit
- •A.24. Getenv
- •A.25. Система
- •A.26. Strerror
- •Приложение B. Встроенные функции
- •B.2. Список встроенных функций
- •Приложение C. Диагностика
- •Приложение D. Компиляторы Си PIC18 и PIC24/dsPIC
- •D.6. Использование стека
- •D.11. Банк доступа
- •D.12. Inline ассемблер
- •D.13. Прагмы
- •D.14. Модели памяти
- •D.15. Соглашения о вызове
- •D.16. Код запуска
- •D.17. Управляемые компилятором ресурсы
- •D.18. Оптимизация
- •D.20. Определяемое реализацией поведение
- •D.21. Битовые поля

16-битовый компилятор Си. Руководство
точкой в адрес, где располагается 16-битовое целое, что приведет к изменению переменной, расположенной сразу после нашей i.
В случаях, когда существуют только weak определения, компоновщик выберет память первого такого определения. Остальные определения становятся недоступны.
Поведение идентично, независимо от типа символа; функции и переменные ведутся себя одинаково.
2.3.2. Определение атрибутов функций
С помощью атрибутов функций вы объявляете отдельные сведения о функциях, |
|
вызываемых в вашей программе, что помогает |
. |
компилятору оптимизировать вызов |
|
A |
|
функций и более тщательно проверять ваш код. |
|
Ключевое слово __attribute__ позволяет вам определять специальные атрибуты в процессе декларации. За этим ключевым словом следует вспомогательная спецификация в двойных круглых скобках. К настоящему времени поддерживаются следующие атрибуты функций:
• address (addr) |
|
Wilson |
• alias ("target") |
|
|
• auto_psv, no_auto_psv |
||
• boot |
|
|
• const |
|
|
• deprecated |
|
|
• far |
|
|
|
|
|
• format (archetype, string-index, first-to-check) |
||
• format_arg (string-index) |
||
|
by |
|
• interrupt [ ( [ save(list) ] [, irq(irqid) ] [, altirq(altirqid)] |
||
[, preprologue(asm) ] ) ] |
|
•• nearTranslated
no instrument function
• noload
• noreturn
• section ("section-name")
• secure
• shadow
• unused
• user init
• weak
Вы можете также определить атрибуты с помощью __ (двойного подчеркивания) перед и после каждого ключевого слова (например, __shadow__ вместо shadow). Это позволяет вам использовать их в файлах заголовка, не беспокоясь о возможности макро с тем же самым именем.
Вы можете определить несколько атрибутов в декларации разделяя их запятыми в пределах двойных круглых скобок или путем непосредственного следования одного определения атрибута за другим определением.
address (addr)
Атрибут address определяет абсолютный адрес для функции. Этот атрибут не может быть использован в сочетании с атрибутом section; атрибут address будет иметь приоритет.
void __attribute__ ((address(0x100))) foo() {
DS51284H(ru) стр. 2-10 |
© 2008 Microchip Technology Inc. |

Глава 2. Отличия 16-битового компилятора от ANSI
...
}
Кроме того, Вы можете определить адрес в прототипе функции:
void foo() __attribute__ ((address(0x100)));
alias ("target")
Атрибут alias приводит к тому, что создается декларация псевдонима для другого символа, который должен быть определен.
Использование этого атрибута имеет следствием внешнюю ссылку, которая должна быть раскрыта на этапе компоновки.
Атрибут auto_psv, использованный совместноA с атрибутом прерывания, заставит компилятор генерировать дополнительный код в прологе функции для записи в SFR PSVPAG значения, необходимогоWilsonпри доступе к space(auto_psv) переменным
auto_psv, no_auto_psv |
. |
|
(или константам в модели памяти consta ts-in-code). Применяйте эту опцию при
использовании 24-битовых указателей и возможности прерывания в то время как PSVPAG модифицирован, а программа обработки прерывания или вызываемая ей
функция используют переменные auto psv. Сравните с no_auto_psv. Если ни
auto_psv ни no_auto_psv опции не определены для программы обработки
прерывания, компилятор выдаст предупреждение и выберет атрибут auto_psv.
Атрибут no_auto_psv, использованный совместно с атрибутом прерывания,
заставит компилятор отказаться от генерации дополнительного кода для доступа к
space(auto_psv) переменным (или константам в модели памяти constants-in-
code). Используйте эту опцию, если ни одно из условий для auto_psv не истинно. Если ни auto_psv ни no_auto_psv опции не определены для программы обработки
прерывания, компилятор выдаст предупреждение и предположит задание атрибута |
|
auto_psv. |
by |
Translated |
|
boot |
|
Этот атрибут заставляет компилятор поместить функцию в сегмент загрузки программной flash памяти.
Например, декларация защищенной функции: void attribute__((boot)) func();
Необязательный аргумент может быть использован, чтобы определить точку входа защищенного доступа в пределах сегмента boot. Аргумент может быть целой константой в диапазоне от 0 до 31 (кроме 16), или словом unused. Целый аргумент соответствует 32 слотам команд в области доступа к сегменту, которая занимает диапазон самых младших адресов каждого безопасного сегмента. Величина 16 исключена поскольку вход доступа 16 зарезервирован за вектором прерывания безопасного сегмента. Величина unused применяется, чтобы определить функцию для всех неиспользованных слотов в области доступа.
Точки входа доступа облегчают создание сегментов приложений от разных поставщиков, которые объединяются на этапе исполнения. Они могут быть определены для внешних функций, также как и для локально определенных функций. Например:
/* внешняя функция, которую мы хотим вызывать */ extern void __attribute__((boot(3))) boot_service3();
/* локальная функция доступная для вызова из других сегментов */ void __attribute__((secure(4))) secure_service4()
{
boot_service3();
}
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-11 |

16-битовый компилятор Си. Руководство
Для определения безопасного обработчика прерывания, используйте атрибут boot в комбинации с атрибутом прерывания:
void __attribute__((boot,interrupt)) boot_interrupts();
Когда точка входа доступа определяется для внешней безопасной функции, эта функция не обязательно должна быть включена в проект для успешной компоновки. Все ссылки на эту функцию будут разрешены по фиксированному адресу во flash памяти, в зависимости от модели безопасности выбранной на этапе компоновки.
Когда точка входа доступа определена для локальной функции, компоновщик вставит команду ветвления в область доступа к безопасному сегменту. Исключение делается только для входа доступа 16, который представлен как вектор (то есть
адрес инструкции), |
а не инструкция. Фактическое определение |
функции |
будет |
|
располагаться за |
A |
область |
доступа |
будет |
областью доступа; следовательно. |
содержать таблицу переходов, через которую управление может быть передано от другого безопасного сегмента к функциям с заданными точками входа.
Автоматические переменные принадлежат включающей их функции и не требуют атрибута boot. Начальные значения могут присваиваться им, как показано:
void __attribute__((boot)) chuck cookies()
{ |
|
Wilson |
int hurl; |
|
|
int them = 55; |
|
|
символ *where = "far"; |
||
splat(where); |
by |
|
/* ... */ |
|
|
|
|
}
Заметьте, что начальное значение для where представляет строковый литерал,
const
который расположен в секции констант PSV .boot_const. Компилятор запишет в PSVPAGTranslatedнеобходимую величину при входе в функцию. Если необходимо, компилятор также восстановит PSVPAG после вызова splat().
Многие функции не проверяют других величин, кроме своих аргументов, и не производят никаких воздействий, кроме возврата значения. Такая функция может быть поводом к устранению общего подвыражения и оптимизации цикла подобно арифметическому оператору. Эти функции должны быть объявлены атрибутом const. Например:
int square (int) __attribute__ ((const int));
показывает, что гипотетическую функцию возведения в квадрат можно с уверенностью вызвать меньшее количество раз, чем указано в программе.
Заметьте, что функция, которая имеет указатели в качестве аргументов и проверяет указанные ими данные не должна быть объявлена как const. Аналогично, функция, которая вызывает не const функцию, обычно также не должна быть const. Не имеет смысла для функции с атрибутом const возвращать значение типа void.
deprecated
См. п. 2.3.1. «Определение атрибутов переменных» для информации об атрибуте deprecated.
far
Атрибут far сообщает компилятору, что функция не должна вызываться с использованием более эффективной формы команды вызова.
DS51284H(ru) стр. 2-12 |
© 2008 Microchip Technology Inc. |

Глава 2. Отличия 16-битового компилятора от ANSI
format (archetype, string-index, first-to-check)
Атрибут format определяет, что функция имеет аргументы стиля printf, scanf или strftime, которые должны быть сверены по типу со строкой формата. Например, рассмотрите декларацию:
extern int my_printf (void *my_object, const char *my_format,...) __attribute__ ((format (printf, 2, 3)));
Она заставляет компилятор проверить аргументы вызова my_printf на соответствие строке формата my_format, заданной в стиле printf.
Параметр archetype определяет, как интерпретируется строка формата, и должен |
||
быть одним из |
printf, scanf или |
. |
strftime. Параметра string-index |
определяет, какой аргумент задает строку формата (аргументы нумеруются слева,
начиная с 1), тогда как first-to-check является номером первого аргумента, |
|
сверяемого со строкой формата. В функциях,A |
где аргументы недоступны для |
Wilson |
|
проверки (как, например, vprintf), определяйте третий параметр как нуль. В этом случае, компилятор только проверяет строку формата на соответствие.
В вышеприведенном примере строка формата (my_format) является вторым аргументом функции my_print, и аргументы, подлежащие проверке, начинаются с третьего, так что правильные параметры для атрибута format — 2 и 3.
Атрибут формата позволяет вам так определить ваши собственные функции, которые принимают строки формата как аргументы, чтобы компилятор мог проверить их вызовы на ошибки. Компилятор проверяет форматы для библиотечных
функций ANSI printf, |
fprintf, sprintf, scanf, fscanf, sscanf, |
|
strftime, vprintf, |
by |
vfprintf и vsprintf, всякий раз, когда бы не |
|
|
запрашивались такие проверки (с использованием -Wformat), так что нет необходимости модифицировать файл заголовка stdio.h.
format_arg (string-index)
Атрибут определяет, что функция принимает аргументы стиля
или scanf, модифицирует их (например, чтобы перевести их на другой язык) и
передает их в функцию стиля printf или scanf. Например, рассмотрим декларацию:
extern char *my dgettext (char *my_domain, const char *my_format) __attribute ((format_arg (2)));
Это заставляет компилятор проверить аргументы в вызове функции my_dgettext, чей результат передается в функции стиля printf, scanf или strftime, на соответствие строке формата в стиле printf, заданной аргументом my_format.
Параметр string-index определяет номер аргумента, являющегося строкой формата (начиная с 1).
Атрибут format arg позволяет вам определять ваши собственные функции, которые модифицируют строки формата, так что компилятор может проверить вызовы функций printf, scanf или strftime, чьи операнды являются вызовом одной из ваших собственных функций.
Translatedformat arg printf
interrupt [ ( [ save(list) ] [, irq(irqid) ] [, altirq(altirqid)] [, preprologue(asm) ] ) ]
Используйте эту опцию, чтобы указывать, что определяемая функция является обработчиком прерывания. При наличии этого атрибута компилятор сгенерирует последовательности пролога и эпилога функции, пригодные для использования в обработчике прерываний. Необязательный параметр save определяет список переменных, которые нужно сохранять и восстанавливались в прологе и эпилоге функции, соответственно. Необязательные параметры irq и altirq определяют идентификаторы используемой таблицы векторов прерывания. Необязательный параметр preprologue определяет код на ассемблере, который должен быть вставлен перед сгенерированным компилятором кодом пролога. См. главу 8 «Прерывания» для полной информации, включая примеры.
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-13 |

16-битовый компилятор Си. Руководство
При использовании атрибута interrupt, пожалуйста определите атрибуты no_auto_psv или auto_psv. Если ни один из них не будет определен, будет выдано предупреждение и предположено наличие атрибута auto_psv.
near
Атрибут near сообщает компилятору, что функция может быть вызвана, используя более эффективную форму инструкции вызова.
no_instrument_function
Если задается опция командной строки -finstrument-function, будут сгенерированы вызовы профилирующих функций на входе и выходе большинства компилированных пользователем функций. Функции с этим атрибутом не будут
оснащены такой возможностью. |
. |
noload |
A |
|
Атрибут noload указывает, что пространство для функции должно быть выделено, но |
|
noreturn |
Wilson |
что фактический код не должен быть загружен в память. Этот атрибут может быть |
полезным, если приложение сконструировано таким образом, что функция загружается в память во время исполнения, например, из последовательной EEPROM.
void bar() __attribute__ ((no oad)) {
...
}
Несколько стандартных библиотечных функций, как, например, abort и exit, не могут делать возврат. Компилятор знает об этом. Некоторые программы
определяют свои собственные функции, не имеющие возврата. Вы можете объявить |
|
их атрибутом noreturn, чтобыby |
сообщить компилятору об этом. Например: |
Translated |
|
void fatal (int i) __attribute__ ((noreturn));
void
fatal (int i)
{
/* Печать сообщения об ошибке */ exit (1);
}
Ключевое слово noreturn сообщает компилятору, что функция fatal не может иметь возврата. Это позволяет при последующей оптимизации отбросить анализ того, что случилось бы, если fatal когда-либо выполнила возврат. Это позволяет слегка улучшить код. Также, это помогает избегать ложных предупреждений о неинициализированных переменных.
Не имеет смысл для noreturn функции иметь какой-либо возвращаемый тип, кроме void.
section ("section-name")
Обычно компилятор помещает созданный код в секцию .text. Иногда, тем не менее, вам нужны дополнительные секции, или вам требуется разместить определенные функции в специальных секциях. Атрибут section определяет местоположение функции в конкретной секции. Например, рассмотрим декларацию:
extern void foobar (void) __attribute__ ((section (".libtext")));
Это поместит функцию foobar в секцию .libtext.
DS51284H(ru) стр. 2-14 |
© 2008 Microchip Technology Inc. |

Глава 2. Отличия 16-битового компилятора от ANSI
Атрибут section конфликтует с атрибутом address. При совместном использовании имя секции будет проигнорировано с предупреждением.
secure
Этот атрибут заставляет компилятор разместить функцию в безопасном сегменте программной flash памяти.
Например определение защищенной функции:
void __attribute__((secure)) func();
Необязательный аргумент может быть использован, чтобы определить точку входа
защищенного доступа в пределах secure сегмента.. Аргумент может быть целой
самый младший дипазон адресов каждого безопасного сегмента. Величина 16
константой в диапазоне от 0 до 31 (кроме 16) или словом unused. Целые аргументы соответствуют 32 слотам команд в области доступаA сегмента, которая занимает
исключена, поскольку вход доступа 16 зарезервирован для вектора прерывания безопасного сегмента. ВеличинаWilsonunused применяется, чтобы определить функцию для всех неиспользованных слотов в области доступа.
Точки входа доступа облегчают создание сегментов приложений от разных поставщиков, которые объединяются на этапе исполнения. Они могут быть определены для внешних функций, также как и для локально определенных функций.
Например:
/* внешняя функция, которую мы хотим вызывать */
extern void __attribute__((boot(3))) boot_service3();
/* локальная функция доступная для вызова из других сегментов */ by
void __attribute__((secure(4))) secure_service4()
{
boot_service3();
} Translated
Для того, чтобы определить безопасный обработчик прерывания, используйте атрибут secure в комбинации с атрибутом прерывания:
void attribu __((secure,interrupt)) secure_interrupts();
Когда точка входа доступа определена для внешней безопасной функции, то функция не обязательно должна быть включена в проект для успешной компоновки. Все ссылки на эту функцию будут разрешены по фиксированному адресу во flash памяти, в зависимости от модели безопасности выбранной на этапе компоновки.
Когда точка входа доступа определена для функции, определенной локально, компоновщик вставит команду ветвления в область доступа безопасного сегмента. Исключение делается только для входа доступа 16, который представлен как вектор (то есть адрес инструкции), а не инструкция. Фактическое определение функции будет располагаться за областью доступа; следовательно область доступа будет содержать таблицу переходов, через которую управление может быть передано от другого безопасного сегмента к функциям с определенными точками входа.
Автоматические переменные принадлежат включающей их функции и не требуют атрибута secure. Начальные значения могут быть присвоены им, как показано:
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-15 |