Разработка устройств на основе цифровых сигнальных процессоров фирмы Analog Devices с использованием Visual DSP++ - Олег Вальпа 10 стр.


Текст программы

/*********************************************************************/

/* Эта программа транслирует данные от ведущего процессора ADSP-2181 */

/* к ведомому процессору ADSP-2181 через IDMA порт */

/*********************************************************************/

.module/abs=0x0000 idma_transfer;

.include <def2181.h>; { Включить файл определений }

.const length=68; { Десятичное значение длины вектора }

.var/pm/ram x_input[length]; { Описание массива данных }

.init x_input: <idmaidma.dat>; { Файл передаваемых данных }

jump start; nop; nop; nop; { Таблица векторов прерываний }

RTI; NOP; NOP; NOP; { Прерывания не используются }

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

RTI; NOP; NOP; NOP;

/*** Начало программы ***/

start:

ax0=0x0000;

dm(System_Control_Reg)=ax0; { Такты ожидания PM отключить }

dm(PFTYPE)=ax0; { Все флаги PF назначить выходами }

dm(DM_Wait_Reg)=ax0; {Такты ожидания DM и портов ввода-вывода отключить}

l6=0; { Длина буфера данных }

i6=^x_input; { Адрес начала буфера транслируемых данных }

m6=1; { Приращение = 1 }

modify(i6,m6); { Модификация адреса }

/*** Защелкнуть адрес 0x0001 ***/

call check_ack; { Проверить готовность к приему }

ax0=0x0001; { Стартовый адрес для записи в ведомый процессор }

io(0x0001)=ах0; { Запись этого адреса с переключением линий -IS и IAL }

/*** Запись всех данных начиная с адреса 0x0001 ***/

cntr=length-1; { Установить счетчик транслируемых слов }

do loop1 until се; { Организовать цикл записи }

call check_ack; { Проверить готовность к приему }

call format; { Форматировать данные }

io(0x0100)=ay0; { -IWR и IS записывают старшие 16 бит IAD 0-15 }

call check_ack; { Проверить готовность к приему }

io(0x0100)=ay1; { -IWR и IS записывают младшие 8 бит IAD 0-15 }

loop1: nop;

/*** Защелкнуть адрес 0x0000 ***/

call check_ack; { Проверить готовность к приему }

ax0=0x0000; { Стартовый адрес для записи в ведомый процессор }

io(0x0001)=ax0; { Запись этого адреса с переключением линий -IS и IAL }

/*** Запись по адресу 0x0000 ***/

i6=^x_input; { Указатель на начало буфера данных }

call check_ack; { Проверить готовность к приему }

call format; { Форматировать данные }

io(0x0100)=ay0; { -IWR и IS записывают старшие 16 бит IAD 0-15 }

call check_ack; { Проверить готовность к приему }

io(0x0100)=ay1; { -IWR и IS записывают младшие 8 бит IAD 0-15 }

idle; { Режим ожидания }

/****************************************************************/

/* Подпрограмма переформатирования 24-бит слова памяти программ */

/****************************************************************/

format: ay0=pm(i6,m6); { 16 старших бит запомнить в регистре ay0 }

ay1=px; { 8 младших бит запомнить в регистре ay1 }

rts;

/***************************************************************************/

/* Подпрограмма ожидания перехода состояния линии -IACK в низкое состояние */

/***************************************************************************/

check_ack:

ax0=dm(0x3fе5); { Читать PF1, который подключен к -IACK }

ar=tstbit 1 of ax0; { Анализировать PF1 }

if ne jump check_ack; { Если процессор не готов вновь контролировать -IACK}

rts;

.endmod;

Многие директивы и команды данной программы уже знакомы читателям из описания предыдущей программы. Текст программы прокомментирован, что позволяет без труда понять алгоритм ее работы. Как видно из текста, в программе использован ряд подпрограмм, в которых сосредоточены часто используемые операции. Вызов данных подпрограмм осуществляется командой call, после которой записывается имя подпрограммы. Команда io(0x0001)=ax0 осуществляет запись содержимого регистра ax0 в порт ввода- вывода по адресу 0x0001. Команда ar=tstbit 1 of ax0 заносит в регистр ar результат тестирования первого разряда регистра ax0. Следующая за этой, команда if ne jump check_ack проверяет состояние флагов ALU и осуществляет переход на метку check_ack, если результат проверки предыдущей операции был отрицательным. Подробнее со всеми командами сигнального процессора ADSP-2181 мы познакомимся позже.

При компиляции этой программы, все данные из файла idmaidma.dat будут автоматически помещены в файл загрузки idmaidma.lda. В качестве файла данных idmaidma.dat можно использовать загрузочный файл рассмотренной нами ранее программы mem_clr.lda, из которого предварительно следует удалить первые три и последние две служебные строки. Данную операцию можно выполнить с помощью любого текстового редактора. После чего файл необходимо переименовать, задав ему имя idmaidma.dat. Кроме того, можно изменить имя загружаемого файла в самой программе.

Глава 11. Директивы ассемблера

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

На примере программ, рассмотренных ранее, было показано, что программа может включать в себя строки различных директив. Директивы управляют процессом ассемблирования. Они обрабатываются препроцессором, но в отличие от инструкций не генерируют при ассемблировании код. Любая директива ассемблера начинается с точки и заканчивается точкой с запятой. Некоторые директивы имеют параметры и аргументы. Параметры следуют сразу за директивой и разделяются косой чертой, аргументы следуют после параметров. Директивы ассемблера могут содержать однострочный комментарий, который не может быть продолжен на следующей строке. Если требуется многострочный комментарий, необходимо начать новый комментарий на следующей строке. В общем случае запись директив выглядит следующим образом:

.ДИРЕКТИВА [/ПАРАМЕТР1][/ПАРАМЕТР2] ... [АРГУМЕНТ]; {Комментарий}

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

Помимо директив ассемблера, в среде разработки программ для ADSP-2181 существует несколько директив для системного конфигуратора. Ранее говорилось о том, что системный конфигуратор можно не использовать, если имеется готовый файл описания архитектуры с расширением ach для конкретного устройства, построенного на определенном типе сигнального процессора. Этот файл используется компоновщиком и программой эмулятора для того, чтобы определить размер памяти системы, тип памяти процессора (ОЗУ или ПЗУ), какая часть памяти является внутренней и внешней и какая периферия отображена в памяти. При необходимости, можно воспользоваться системным конфигуратором с целью получения нового файла описания архитектуры для нового устройства или другого типа процессора.

Перед запуском системного конфигуратора необходимо создать файл с расширением sys, содержащим директивы описания устройства (системы). Запуск системного конфигуратора осуществляется командой:

bld21 имя_файла[sys] [-c]

Здесь имя_файла - это имя исходного файла системной конфигурации. Имя файла может быть указано с расширением. Если расширение отсутствует, системный конфигуратор добавляет по умолчанию расширение sys. Системный конфигуратор создает выходной файл описания архитектуры с именем входного файла и расширением ach. Ключ -с делает системный конфигуратор чувствительным к регистру символов, различающим использование верхнего или нижнего регистра (прописных или строчных) символов. Если ключ -с не используется, то на выходе системного конфигуратора будет создан файл с символами верхнего регистра. Для вызова справки системного конфигуратора, наберите команду:

bld21 -help

Этот ключ позволяет получить справку о версии программы и посмотреть список возможных команд. Ключ -help работает в большинстве программ средств разработки.

Рассмотрим более подробно основные директивы системного конфигуратора и ассемблера для сигнальных процессоров семейства ADSP.

Директива SYSTEM

Директива SYSTEM определяет имя (название) системы и должна быть первой командой в исходном файле системной конфигурации. Директива имеет формат:

.SYSTEM имя_системы;

В языке ассемблера допускается использовать в качестве имен набор символов, содержащий:

- прописные латинские буквы от "A" до "Z";

- строчные латинские буквы от "a" до "z";

- знак подчеркивания "_".

Имена не должны начинаться с цифры и могут иметь длину до 32 знаков. Ниже приведено несколько примеров имен с описанием их назначения:

Main_prog {Программный модуль на языке ассемблер}

var1 {Переменная};

buff {Буфер данных};

met173 {Программная метка};

DAC {Порт, отображенный в памяти}.

Директива ADSP21XX

Эта директива определяет, какой тип процессора семейства ADSP2100 используется в системе. Данная информация передается компоновщику (редактору связей) и симулятору через выходной файл с расширением ach. После этого редактор связей в состоянии определить место расположения программы и данных в соответствии с организацией памяти для конкретного типа процессора. Эта директива принимает одну из следующих форм:

.ADSP2100; {Для ADSP-2100 и ADSP-2100A}

.ADSP2101;

.ADSP2105;

.ADSP2111;

.ADSP2150; {Для ADSP-21msp50 и ADSP-21msp55}

.ADSP2151; {Для ADSP-21msp51 и ADSP-21msp56}

.ADSP2101MV; {Для вариантной системы ADSP-2101 (ADSP-2115)}

.ADSP2101P; {Для системы со страничной памятью ADSP-2101}

.ADSP2181; {Для ADSP-2181}

и т.п.

Директива MMAP

Эта директива определяет логическое состояние вывода MMAP процессора в системе. Она принимает одну из двух форм:

.MMAP0 {Вывод MMAP=0}

.MMAP1 {Вывод MMAP=1}

Если используется MMAP0, загрузка программы из памяти начальной загрузки происходит после перезагрузки и начинается с нулевого адреса внутренней памяти программ. Если используется MMAP1, загрузка программы из памяти начальной загрузки недоступна, и внутренняя память программ отображается на верхние адреса пространства памяти программ. Когда эта директива пропускается, программа моделирования принимает по умолчанию значение MMAP1.

Директива SEG

Директива SEG определяет специальную секцию системной памяти и описывает ее атрибуты. Не существует разделения памяти по умолчанию, поэтому необходимо определить системную память с помощью директив SEG самостоятельно. Эта информация передается редактору связей, симулятору и эмулятору через выходной файл с расширением ach. Директива SEG имеет форму:

.SEG/параметр1/параметр2/... имя_сегмента[размер];

Сегменту присваивается символьное имя. Присвоенное имя позволяет разместить фрагменты программы и данных в памяти. На языке ассемблер это достигается параметром SEG. Размер сегмента указывается внутри скобок. Эта величина интерпретируется как количество 16-разрядных слов данных или 24-разрядных слов инструкций в сегменте.

Для директивы SEG необходимо указать два обязательных параметра:

PM, или DM, или BOOT=0-7 - тип сегмента памяти;

RAM или ROM - тип памяти процессора.

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

ABS=адрес - абсолютный стартовый адрес;

DATA, или CODE, или DATA/CODE - тип данных, хранимых в сегменте;

EMULATOR или TARGET - распределение памяти для эмулятора;

INTERNAL - расположение в памяти процессора ADSP-2101 с вариантной памятью.

Параметры PM, DM и BOOT определяют тип сегмента памяти, который может быть отведен под память программ, память данных или одну из восьми страниц памяти начальной загрузки. Остальные параметры определяют тип памяти процессора, начальный адрес сегмента, тип данных сегмента (данные и/или программы) и распределение памяти эмулятора.

Каждый сегмент памяти должен адресоваться раздельно, поскольку, например, адрес 0x10 в памяти программ отличается от адреса 0x10 в памяти данных из-за разной длины слов этих данных. Сегмент памяти программ PM может хранить только программы (CODE), данные (DATA) или одновременно программы и данные. Если не указать ни одну из опций, по умолчанию принимается хранение программ. Для сегмента PM, содержащего программу и данные, должны быть указаны оба параметра. Параметр памяти начальной загрузки должен определять только один номер страницы, например BOOT=0. Необходимо разделять объявление сегмента для каждой страницы памяти начальной загрузки системы. Система может иметь до 8 страниц памяти начальной загрузки с номерами от 0 до 7. Каждая страница памяти начальной загрузки для ADSP-2101, ADSP-2111, ADSP21ms50 может сохранять до 2К программ и данных. Каждая страница памяти начальной загрузки для ADSP-2105, ADSP-2115 может сохранять до 1К слов. Параметр ABS для страниц памяти начальной загрузки не используется, поскольку системный конфигуратор самостоятельно присваивает соответствующие адреса.

Примеры директивы SEG:

.SEG/PM/RAM/ABS=0/CODE/DATA start [2048];

Здесь объявлен сегмент памяти программ ОЗУ, называемый start, который расположен по адресу 0. Сегмент может содержать до 2048 слов программ и данных.

.SEG/ROM/BOOT=0 boot0[1536];

Здесь объявлен сегмент памяти начальной загрузки boot0, который расположен на странице номер 0 памяти начальной загрузки (автоматически соответствует адресу 0 в памяти начальной загрузки). Длина сегмента составляет 1536 слов. Сегменты памяти начальной загрузки должны всегда быть объявлены как ROM (ПЗУ).

Директива PORT

Директива PORT является директивой системного построителя и ассемблера. Она объявляет порт ввода/вывода отображенный в памяти процессора. Каждый порт должен иметь уникальное имя и адрес в системе. Порты могут быть определены в памяти данных или памяти программ. Для процессоров с внутренней памятью портам могут быть присвоены адреса только во внешней памяти.

Директива PORT принимает одну из двух форм:

.PORT/DM/ABS=адрес имя_порта;

или

.PORT/PM/ABS= адрес имя_порта;

Параметр DM показывает, что порт отображен в памяти данных. Параметр PM показывает, что порт отображен в памяти программ. Если параметр не задан, по умолчанию принимается DM. Порт располагается по абсолютному адресу, который определен параметром ABS, и присваивается символическому имени порта. Это имя используется в инструкциях ассемблера для доступа к порту, например:

.PORT/DM/ABS=0x0020 p1;

Объявляет имя порта p1, который отображен в памяти данных по адресу 0x0020 (шестнадцатеричный) или 32 (десятичный). Ассемблерная программа обращается к этому имени, чтобы представить его редактору связей, базирующемуся на содержании файла описания системной конфигурации с расширением ach. Отображение порта в памяти данных позволяет 16-и разрядное чтение/запись, в то время как отображение порта в памяти программ допускает 16- или 24-разрядный обмен данными.

В программе директива PORT повторяет директиву системного построителя без указания адреса порта. Например, в файле конфигурации системы для системного построителя директива PORT объявляет порты CODEC и DAC по адресам 0x3000 и 0x3800 соответственно:

.PORT/ABS=0x3000 CODEC;

.PORT/ABS=0x3800 DAC;

В программе директива PORT объявляет эти порты следующими строками:

.PORT CODEC;

.PORT DAC;

После чего в программе можно делать обращения к описанным портам с помощью команд, подобным следующим:

AR=DM(DAC);

DM(DAC)=AR;

AR=DM(CODEC);

DM(CODEC)=AR;

Назад Дальше