Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Микропроцессорная техника Сторожок / MPLAB_C30_Руководство пользователя.pdf
Скачиваний:
161
Добавлен:
20.02.2016
Размер:
1.26 Mб
Скачать

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

Соседние файлы в папке Микропроцессорная техника Сторожок