Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
686.docx
Скачиваний:
84
Добавлен:
24.04.2019
Размер:
6.68 Mб
Скачать

5 Инструментальные средства для работы со стендом

SDK-1.1

В

данной

главе

рассматривается

инструментальная

цепочка

программирования контроллера SDK-1.1, в которую входят бесплатные с

открытым исходным кодом инструментальные средства по разработке

программного обеспечения и доставке исполняемых модулей в учебный стенд

SDK-1.1.

5.1 Программирование стенда sdk-1.1

Для программирования стенда может использоваться любой транслятор

ассемблера или C для ядра 8051, например, SDCC или пакет μVision от Keil

Software.

Рисунок 93. Этапы программирования стенда SDK-1.1

Основные

этапы

программирования

стенда

использованием

компилятора SDCC):

 Подготовка

программы

в

текстовом

редакторе

или

среде

программирования.

 Транслирование исходного текста, сборка и получение загрузочного

HEX-модуля программы при помощи компилятора SDCC.

 Подготовка и загрузка исполняемого модуля в стенд через интерфейс

RS-232C

с

помощью

инструментальной

системы

(M3P).

Под

подготовкой понимается преобразование загрузочного модуля из HEX-

формата в бинарный образ.

221

 Прием и обработка исполняемого модуля резидентным загрузчиком

UL3, который находится во Flash-памяти стенда SDK-1.1. Загрузчик

записывает программу во внешнюю память программ и данных по

указанному адресу и передает ей управление тоже по указанному

адресу.

Далее

будут

рассмотрены

все

программные

средства

описанной

инструментальной цепочки программирования стенда SDK-1.1, которые

используются на стороне персонального компьютера.

5.2 Компилятор sdcc

SDCC (Small Device C Compiler) – бесплатный с открытым исходным

кодом, переносимый, оптимизирующий ANSI C компилятор для 8-разрядных

микроконтроллеров на базе Intel MCS51, Maxim 80DS390, Zilog Z80, Motorola

68HC08. Распространяется под лицензией GNU GPL. SDCC использует

бесплатные, способные полностью перенастраиваться на новые платформы

ассемблер и линкер. SDCC обладает расширенным набором команд,

основанном на оригинальном наборе команд микроконтроллеров на базе Intel

8051, что позволяет ему более эффективно использовать аппаратные

возможности конкретной платформы [16].

5.2.1

Опции командной строки компилятора

222

Ключ

Описание

-I

Добавляет каталог «директория» в начало списка каталогов,

используемых для поиска заголовочных файлов. Ее можно

использовать для подмены системных заголовочных файлов,

подставляя ваши собственные версии, поскольку эти директории

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

Если вы используете более чем одну опцию '-I', директории

просматриваются в порядке слева направо; стандартные системные

директории идут после.

-c

Компилировать или ассемблировать исходные файлы, но не

линковать. Конечный вывод происходит в форме объектного файла

для каждого исходного файла.

-mmcs51

Выбирает семейство микроконтроллеров Intel MCS51, для которого

производится компиляция. Опция необязательна, т.к. это семейство

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

соответствующие ключи компиляции необходимо указывать (-mds390,

-mz80, -mhc08 и др.)

--model-small

--model-medium

--model-large

Выбирает модель памяти. Модель памяти small выбирается по

умолчанию. В моделях medium и large все переменные без

модификатора памяти попадают по умолчанию во внешнее ОЗУ

(XRAM). В модели памяти small все переменные без модификатора

памяти попадают во внутреннюю память данных (RAM).

--xstack

Позволяет располагать стек во внешней памяти (первые 256 байт), в

5.2.2

Классы памяти

Компилятор SDCC поддерживает инструмент, позволяющий управлять

механизмами использования памяти в микроконтроллерах семейства Intel

MCS51 и создавать мощные и гибкие программы. Этот инструмент – классы

памяти. Каждая переменная может принадлежать к одному из 7 классов памяти.

Класс памяти указывается при помощи специального модификатора.

Таблица 31. Классы памяти (расширение языка Си для МК Intel MCS51)

223

сегменте pdata.

-o <path/file>

Указывает путь/имя исполняемого файла (загрузочного модуля), в

который получается в результате сборки проекта. По умолчанию это

файл в формате Intel HEX.

--stack-auto

Указывает, что все функции в исходных кодах являются

реентерабельными (см. раздел ниже). По умолчанию все функции

являются нереентерабельными, в том числе и функции по работе с 16-

и 32-разрядными переменными (операции умножения, деления и т.д.),

которые входят в стандартную библиотеку SDCC и используются

неявно (можно увидеть только в lst-файлах).

--code-loc

<Value>

Расположение памяти программ (кода). По умолчанию адрес = 0.

Значение стартового адреса (<Value>) может быть указано как в

шестнадцетеричной, так и в десятичной системе счисления: --code-loc

0x8000 или --code-loc 32768.

--xram-loc

<Value>

Расположение внешней памяти данных. По умолчанию адрес = 0.

Значение стартового адреса (<Value>) может быть указано как в

шестнадцетеричной, так и в десятичной системе счисления: --xram-loc

0x8000 или --xram-loc 32768.

--stack-loc

<Value>

Расположение стека. По умолчанию стек располагается после сегмента

данных во внутреннем ОЗУ (например, для МК ADuC812 вершина

стека = 0x07 после старта). Значение стартового адреса (<Value>)

может быть указано как в шестнадцетеричной, так и в десятичной

системе счисления: --stack-loc 0x20 или --stack-loc 32.

Модификаторы

памяти

Описание

data

Внутренняя память данных с прямой адресацией; самая быстрая

работа с переменными (128 байт). Класс памяти по умолчанию для

модели памяти small.

xdata

Внешняя память данных (64Кб-16Мб). Класс памяти по

умолчанию для модели памяти large.

idata

Внутренняя память данных с косвенной адресацией; доступ ко

всему адресному пространству (128/256 байт).

pdata

Внешняя память данных с косвенной адресацией (256 байт). Класс

памяти по умолчанию для модели памяти medium.

code

Память программ (64 Kб).

bit

И класс памяти, и нестанадртный тип данных. Бит-адресуемая

внутренняя память данных (128 бит) в диапазон адресов 20h-2Fh.

sfr/sfr16/sfr32/sbit

И класс памяти, и нестанадртный тип данных. Служит для

определения регистров специального назначения (sfr – 8 разрядов,

sfr16 – 16 разрядов, sfr32 – 32 разряда) и их битов (sbit). Эти

ключевые слова используются для создания заголовочных файлов,

позволяющих обращаться к регистрам специального назначения

по именам.

Обращение к внутренней памяти данных происходит гораздо быстрее, чем

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

размещать во внутренней памяти, а остальные – во внешней. Далее приведены

примеры объявления переменных в разных классах памяти:

__data unsigned char test_data;

__xdata unsigned char test_xdata;

__idata unsigned char test_idata;

__pdata unsigned char test_pdata;

__code unsigned char test_code;

__bit test_bit;

__sfr __at (0x80) P0; // регистр специального назначения P0 по адресу 0x80

/* 16-разрядный регистр специального назначения для Таймера 0

Старший байт значения находится по адресу 0x8C, младший по адресу 0x8A*/

__sfr16 __at (0x8C8A) TMR0;

__sbit __at ( 0xD7 ) CY; /* CY (Carry Flag, флаг переноса в SFR PSW) */

Если в объявлении переменной модификатор памяти не указан, выбирается

модель памяти, установленная по умолчанию. Аргументы функции и

переменные класса памяти auto, которые не могут быть размещены в регистрах,

также хранятся в области памяти, установленной по умолчанию.

Модель

памяти,

выбираемая

в

качестве

модели

по

умолчанию,

устанавливается с помощью опций компилятора small, medium и large.

5.2.3

Абсолютная адресация

Переменным можно присваивать не только класс памяти (data, xdata, code)

но и абсолютный адрес расположения.

__xdata __at (0x7ffe) unsigned int chksum;

В примере, приведенном выше, переменная chksum будет размещена по

адресу 7ffeh во внешней памяти XDATA. Необходимо заметить, что

компилятор не резервирует места под переменные, определенные таким

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

лежит на программисте. Для проверки можно использовать файлы с

расширениями .lst, .rst и .map.

Если вы произведете инициализацию памяти, линкер сможет обнаружить

пересечение данных.

__code __at (0x7ff0) char Id [5] = ''SDCC'';

224

В случае использования устройств ввода-вывода, расположенных в

адресном пространстве внешней памяти, необходимо использовать ключевое

слово volatile, для того, чтобы оптимизатор компилятора не заменил обращение

к устройству, обращением к регистру общего назначения.

volatile __xdata __at (0x8000) unsigned char PORTA_8255;

В SDCC допускается указание абсолютного адреса расположения бита, для

битовых переменных.

__bit __at (0x02) bvar;

Использование абсолютной адресации битовой памяти может вызвать

путаницу, и оправдано только, если вам хочется написать универсальную

программу (см. пример ниже) для нескольких комплектов аппаратных средств.

extern volatile __bit MOSI;

extern volatile __bit MISO;

extern volatile __bit MCLK;

/* master out, slave in */

/* master in, slave out */

/* master clock */

unsigned char spi_io(unsigned char out_byte)

{

unsigned char i=8;

do

{

MOSI = out_byte & 0x80;

out_byte <<= 1;

MCLK = 1;

if (MISO)

out_byte += 1;

MCLK = 0;

} while(-i);

return out_byte;

}

Далее мы видим варианты определения битов для разных аппаратных

средств:

// вариант 1

__bit __at

__bit __at

__bit __at

// вариант 2

__bit __at

__bit __at

__bit __at

(0x80) MOSI;

(0x81) MISO;

(0x82) MCLK;

(0x83) MOSI;

(0x91) MISO;

(0x92) MCLK;

/* I/O port 0, bit 0 */

/* I/O port 0, bit 1 */

/* I/O port 0, bit 2 */

/* I/O port 0, bit 3 */

/* I/O port 1, bit 1 */

/* I/O port 1, bit 2 */

5.2.4

Реентерабельность

В зависимости от модели памяти и количества свободного места,

автоматические переменные и параметры функции могут быть помещены в

стек или в пространство внешней или внутренней памяти. Последний вариант

делает

функцию

нереентерабельной.

Для

того,

чтобы

разместить

автоматические

переменные

в

стеке

можно

воспользоваться

опцией

компилятора --stack-auto (или в тексте программы #pragma stack-auto) или

ключевым словом reentrant при определении функции.

225

unsigned char foo(char i) __reentrant

{

...

}

Необходимо помнить, что в архитектуре MCS51 стек имеет очень

небольшой объем. Поэтому опцией --stack-auto необходимо пользоваться

экономно и с осторожностью. Для решения проблемы с размером стека, можно

явно указывать тип памяти для автоматической переменной и её абсолютный

адрес.

unsigned char foo()

{

__xdata unsigned char i;

__bit bvar;

__data __at (0x31) unsigned char j;

...

}

5.2.5

Оверлеи

В нереентерабельных функциях одна и та же область памяти может быть

использована повторно. SDCC использует оверлеи по умолчанию. Для

отключения режима работы с оверлеями необходимо использовать #pragma

nooverlay.

#pragma save

#pragma nooverlay

void set_error(unsigned char errcd)

{

P3 = errcd;

}

#pragma restore

void some_isr () __interrupt (2)

{

...

set_error(10);

...

}

В приведенном примере использование errcd без #pragma nooverlay

привело бы к непредсказуемым последствиям.

5.2.6

Обработчики прерываний

Обработчик прерывания в SDCC имеет следующий вид:

void timer_isr (void) __interrupt (1) __using (1)

{

...

}

Ключевое слово __interrupt определяет номер вектора прерываний, а слово

__using - номер используемого регистрового банка. Явное указание номера

регистрового банка позволяет уменьшить объем данных, сохраняемых в стеке

226

при вызове обработчика. Предполагается естественно, что этот регистровый

банк кроме обработчика никто не будет использовать.

Если

обработчик

прерывания

изменяет

какие-либо

глобальные

переменные, они должны быть определены с использованием ключевого слова

volatile.

/* Номера обработчиков прерываний для ЬК ADuC812 в стенде SDK-1.1:

адрес = (номер * 8) + 3 */

#define

#define

#define

#define

#define

IE0_VECTOR

TF0_VECTOR

IE1_VECTOR

TF1_VECTOR

SI0_VECTOR

0

1

2

3

4

/*

/*

/*

/*

/*

0x03

0x0b

0x13

0x1b

0x23

external interrupt 0 */

timer 0 */

external interrupt 1 */

timer 1 */

serial port 0 */

5.2.7

Критические секции

Внутри критической секции SDCC генерирует код, который запрещает (в

начале секции) и восстанавливает в исходное состояние (в конце) все

прерывания. Необходимо помнить, что в большинстве случаев запрещать все

прерывания слишком накладно.

int foo () __critical

{

...

...

}

Ключевое слово __critical может использоваться совместно с ключевым

словом reentrant.

Ключевое слово __critical может использоваться для защиты отдельных

переменных.

__critical { i++; }

5.2.8

Семафоры

Архитектура MCS51 позволяет проводить атомарные действия над

битовыми переменными, что позволяет успешно реализовать простой

бинарный

семафор. SDCC

генерирует

такой

код,

если

используется

приведенный ниже шаблон исходного текста.

volatile bit resource_is_free;

if (resource_is_free)

{

resource_is_free=0;

...

resource_is_free=1;

}

Пример использования бинарного семафора.

227

char x = 0;

volatile bit resource_is_free;

void sem( void )

{

if (resource_is_free)

{

resource_is_free = 0;

x = 10;

resource_is_free = 1;

}

}

Генерируемый SDCC код.

jbc _resource_is_free,00106$

ret

00106$:

mov _x,#0x0A

setb _resource_is_free

ret

5.2.9

Ассемблерные вставки

Компилятор

SDCC

позволяет

использовать

ассемблерные

вставки.

Попробуем оптимизировать программу, представленную ниже.

unsigned char __far __at(0x7f00) buf [0x100];

unsigned char head, tail;

void to_buffer( unsigned char c )

{

if( head != (unsigned char)(tail-1) ) buf [ head++ ] = c;

}

В примере оптимизированной функции хорошо видно, что для прямого

включения ассемблерного кода необходимо использовать директивы _asm и

_endasm.

void to_buffer_asm( unsigned char c )

{

_asm

mov r2,dpl

;buffer.c if( head != (unsigned char)(tail-1)

mov a,_tail

dec a

mov r3,a

mov a,_head

cjne a,ar3,00106$

ret

00106$:

;buffer.c buf [ head++ ] = c;

mov r3,_head

inc _head

mov dpl,r3

mov dph,#(_buf >> 8)

mov a,r2

movx @dptr,a

00103$:

ret

228

}

_endasm;

Внутри ассемблерной вставки возможно использование любых директив,

понятных ассемблеру.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]