Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[6]

movlw low 01234h movwf btemp movlw high 01234h movwf btemp+1 return

Значения - структура

Если функция возвращает структуру или объединение (struct, union) размером менее 4 байт, то результат упаковывается как 16-и или 32-х битное значение (см. ранее). Если размер результата превышает 4 байта, то он копируется в специально отведенную область памяти:

struct fred

int ace[4];

struct fred return struct(void)

struct fred wow; return wow;

В результате компиляции будет получен следующий код:

movlw ?a return struct+0 movwf 4

movlw structret movwf btemp movlw 8

GLOBAL structcopy lcall structcopy return

5.5 Вызов функции

Как можно использовать С для процессоров начального уровня лично я не представляю, поэтому и освещать это извращение не буду. В контроллерах среднего и крутого уровня наличествует стек возвратов нормального размера (или около того), что уже делает допустимым полноценное использование процедурных языков программирования, но никак не объектно-ориентированных!

Локальные переменные

С поддерживает два класса локальных переменных: автоматические переменные, память под которые выделяется динамически из нулевого банка, и статические переменные, которые всегда располагаются в фиксированных адресах памяти.

Автоматические переменные

По умолчанию все переменные, описанные в теле функции относятся к этому классу. Исключение составляют те переменные в описании которых явно присутствует ключевое слово static. К автоматическим переменным не могут применяться квалификаторы, так как отсутствует контроль над выделением памяти. Исключение составляют только такие квалификаторы как const и volatile.

Все автоматические переменные располагаются в нулевом банке памяти.

Каждая функция имеет собственную область памяти в которой размещаются автоматические переменные. Эти области могут пересекаться для функций, которые, по мнению компоновщика, никогда не вызываются одновременно.

Статические переменные

Статические переменные всегда располагаются в фиксированных адресах памяти и


никогда не пересекаются с другими областями. При этом, они могут быть непосредственно доступны только из той функции, в которой описаны. Хотя к ним можно получить косвенный доступ из любого места программы, воспользовавшись указателями. Для статических переменных гарантируется сохранение их значения между вызовами функции. Исключение составляет случай косвенного изменения содержимого статической переменной с помощью указателя.

Статические переменные, которые инициализируются в описании, реально инициализируются только один раз, при запуске программы. В этом смысле они отличаются от автоматических переменных, которые инициализируются при каждом вызове функции.

5.6 Управление запуском программы

Далее идет довольно сложный фрагмент в котором объясняются принципы запуска программы при подаче питания. При запуске должны выполняться некоторые служебные процедуры связанные с инициализацией переменных, выделением и распределением памяти, настройкой системы.

Стартовым адресом программы является младший адрес (0х0). В этой точке располагается вызов служебной функции, которая собственно и занимается инициализацией. После общей инициализации вызывается функция main(). Имеется в виду имя функции с точки зрения ассемблерного кода. В тексте С-программы эта функция описывается как main().

Стартовый код находится в стандартном модуле в каталоге lib и называется picrtXXX.obj. Исходный код модуля находится в каталоге sources и называется picrt66x.as. Кроме этого, могут потребоваться процедуры копирования данных или очистки памяти. Исходные тексты этих дополнительных функций вы также можите найти в каталоге sources, например clrbank0.as или cpybank1.as.

Некоторые устройства требуют специальной инициализации при подаче питания. Для реализации этих специальных функций нет необходимости изменять стандартные модули. Компилятор PICC предусматривает возможность выполнения при запуске программы действий необходимых в подобной ситуации. Программист должен создать специальный ассемблерный модуль, который будет выполняться непосредственно после рестарта или подачи питания. Обычно этот модуль внедряют непосредственно файл с С-программой. Пустая процедура запуска (заглушка) находится в файл powerup.as. Этот файл может быть скопирован в ваш проект, модифицирован и использоваться в дальнейшем в качестве исходного кода вашей процедуры запуска. В этом случае она заменит собой процедуру принятую по умолчанию.

При написании собственной процедуры запуска необходимо иметь в виду следующие обстоятельства: минимально использовать память, а лучше вообще не использовать; перед использованием любых системных ресурсов, они должны быть проверены и подключены.

Вот пример стандартной процедуры запуска:

GLOBAL powerup,start PSECT powerup,class=CODE,delta=2 powerup

ljmp start

По сути своей процедура запуска должна быть маленького размера. Это требование обусловлено еще и физическим расположением кода. Дело в том, что процедура запуска размещается в непосредственной близости вектора прерываний. Увеличение размера процедуры может привести к конфликту с обработчиком прерываний.

Если, все таки, возникает необходимость написание большой процедуры запуска, то избежать конфликта поможет следующая техника: GLOBAL powerup,start,big powerup PSECT powerup,class=CODE,delta=2 powerup

ljmp big powerup


PSECT big powerup,class=CODE,delta=2 big powerup

powerup code

ljmp start

5.7 Директивы компилятора

Любой солидный компилятор содержит, так называемый, препроцессор, который делает возможным использовать такие необходимые технологии как макросы, условная компиляция и проч. Такой препроцессор имеется и в PICC. Давайте рассмотрим, какие команды (директивы) могут выполняться этим препроцессором (см. таблицу 6).

Таблица 6 Директивы препроцессора

Директива

Описание

Пустая директива - ничего не делает

#assert

Генерирует ошибку если результат не истина

#assert SIZE > 10

Позволяет внедрять ассемблерный код в программу на С

movlw 10h

#endasm

#define

Описание макроса

#define SIZE 5 #define FLAG #define add(a,b) ((a)+(b))

Сокращение для #else#if

see #ifdef

Включает строки исходного текста по условию

see #if

#endasm

Замыкает внедренный ассемблерный код

see #asm

Замыкает строки исходного текста, включаемые по условию

see #if

Генерирует сообщение об ошибке

#error Size too big

Включает строки исходного текста если условие истинно

#if SIZE < 10

c = process(10)

skip();

Включает строки исходного текста если если символ определен

#ifdef FLAG

do loop(); #elif SIZE == 5

skip loop();

#ifndef

Включает строки исходного текста если если символ не определен

#ifndef FLAG jump();

#include

Подключает внешний текстовый файл к исходному тексту

#include <stdio.h> #include "project.h"

Указывает номер строки и имя файла для листинга

#line 3 final

(где nn - номер) сокращение для #line nn

#pragma

Специальные опции компилятора

См. далее.

Удаляет определенный ранее символ

#undef FLAG

#warning

Выводит предупреждение

#warning Possible conflict



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7]