/ Language: Русский / Genre:comp_hard,ref_ref, / Series: Современная электроника

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

Олег Вальпа

Книга предназначена для самостоятельного изучения и применения на практике цифровых сигнальных процессоров DSP (Digital Signal Processor). На примере популярной микросхемы ADSP2181 фирмы Analog Devices рассмотрены устройство, архитектура и технические характеристики цифрового сигнального процессора. Приведено описание вычислительных блоков процессора, средств разработки программного обеспечения, языка программирования и системы команд процессора. Разработанные автором книги практические схемы с применением сигнального процессора, исходные тексты программ и схемы вспомогательных устройств, полезных при отладке программ для процессора помогут получить необходимые практические навыки, с помощью которых читатель легко освоит другие типы сигнальных процессоров. На прилагаемом к книге диске находятся исходные тексты и исполняемые файлы программ, а так же некоторые полезные утилиты и средства разработки программного обеспечения для сигнальных процессоров. Для специалистов в области разработки цифровой электронной аппаратуры, будет полезна студентам и аспирантам.

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

Предисловие

В настоящее время цифровые сигнальные процессоры, или сокращенно DSP (Digital Signal Processor), приобрели большую популярность в мире и даже признаны отдельной областью науки и техники.

Эта книга является практическим руководством по самостоятельному изучению и применению на практике одного из цифровых сигнальных процессоров фирмы Analog Devices. Она включает в себя подробное описание процессора, схемы для его практического применения и технологию программирования.

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

Состоит из четырех частей: часть I посвящена схемотехнике сигнальных процессоров; в части II рассмотрено программирование устройств; далее в части III описаны вычислительные и аппаратные устройства; в части IV представлены установка, запуск, работа, спектральный анализ сигнала, а также программирование на СИ в среде разработки Visual DSP++.

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

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

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

Автор

Часть I. Схемотехника

В этой части книги освещается история развития различных сигнальных процессоров и дается обзор технических характеристик сигнальных процессоров семейства ADSP-21XX. Кроме того, в ней приводится практическая схема применения процессора ADSP-2181, описываются его архитектура и программно-логическая модель, дается описание системы прерываний процессора.

Глава 1. Обзор

В настоящее время большую популярность приобрели цифровые сигнальные процессоры, или сокращенно DSP (digital signal processor). Эта книга приподнимет завесу таинственности этих компонентов и позволит читателям самостоятельно заняться их освоением и применением в собственных разработках.

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

• Наличие аппаратного умножителя.

• Наличие специальных блоков обработки данных.

• Специальная система команд для цифровой обработки сигналов.

• Высокое быстродействие.

• Внутренний умножитель тактовой частоты.

• RISC архитектура.

• Возможность одновременного выполнения нескольких команд.

• Гарвардская архитектура построения процессора.

• Наличие конвейеризации команд и данных.

• Наличие циклических буферов.

• Развитая система внешних интерфейсов.

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

Проведем небольшой экскурс в историю развития данного семейства процессоров. Первые сигнальные процессоры появились в начале 80-х годов. Одной из первых компаний начавшей производство этих процессоров, была японская корпорация NEC, выпустившая однокристальный сигнальный процессор MPD7720. Однако этот процессор не получил широкого распространения, поскольку в 1982 г. на смену ему пришел более производительный и развитый процессор TMS32010, выпущенный фирмой Texas Instruments. Благодаря удачной архитектуре и ряду технических решений он стал стандартом де-факто для сигнальных процессоров. Ниже приведены основные технические характеристики данного процессора.

Разрядность данных 16 бит

Производительность 5 млн. операций в секунду

Объем оперативной памяти 256 слов

Объем памяти программ 4 К слов

Объем подключаемой внешней памяти 4 К слов

Разрядность арифметико-логического устройства 32 бит

Разрядность умножителя 6×16 бит с 32-битным результатом

Разрядность портов ввода-вывода 16 бит

Количество портов ввода-вывода 8

Пропускная способность внешней шины 50 Мбит

Освоение новых микронных технологий и, как следствие, повышение степени интеграции микросхем позволили значительно улучшить характеристики процессоров. И уже в середине 1980-х годов появились сигнальные процессоры второго поколения. К ним можно отнести процессоры все той же фирмы Texas Instruments TMS320C25 и TMS320C5X. Эти процессоры более скоростные и имеют больший объем памяти. Кроме того, у них появилась развитая система обработки прерываний и энергосберегающие режимы работы. В некоторых моделях процессоров снижено напряжение питания. Появились теневые регистры для автоматического сохранения результатов работы в случае возникновения аппаратного или программного прерывания программы. В состав архитектуры процессора добавились таймеры и последовательные синхронные порты с развитой конфигурацией настройки.

В свою очередь, фирма Motorola выпустила сигнальные процессоры семейства DSP56000, которые имеют разрядность 24 бита, двойную внутреннюю шину данных X и Y, удобную при операциях с комплексными числами, и обладают высокой степенью конвейеризации и параллелизма. Эти свойства делают данные процессоры еще более производительными и удобными для цифровой обработки сигналов.

Еще один производитель в лице фирмы AT&T Microelectronics выпускает сигнальные процессоры серии DSP16, которые отличаются наличием кэш-памяти и встроенного высокоскоростного, до 30 Мбайт, параллельного порта.

Фирма Analog Devices вышла на рынок сигнальных процессоров со своей серией ADSP-21XX, которые конкурируют с выше рассмотренными моделями по некоторым техническим параметрам, а кроме того, по цене. Например, процессор ADSP-21msp50 имеет встроенные АЦП и ЦАП и в то же время его стоимость составляет несколько долларов.

На этом развитие сигнальных процессоров не остановилось, и уже в конце 1980-х годов на рынке появились процессоры третьего поколения от перечисленных выше фирм. Отличительной особенностью этого поколения стало появление двоичной плавающей арифметики, увеличение разрядности шины данных, емкости памяти и программ. К этому числу процессоров можно отнести TMS320C30 фирмы Texas Instruments, DSP96002 фирмы Motorola, DSP32C фирмы AT&T Microelectronics и ADSP21020 фирмы Analog Devices.

Впоследствии на рынке появились сигнальные процессоры других фирм. Однако в настоящее время, лидирующее положение в этой области занимают фирмы Texas Instruments, Motorola, AT&T Microelectronics и Analog Devices.

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

Глава 2. Архитектура

В этой главе описывается внутренняя архитектура одного из сигнальных процессоров фирмы Analog Devices ADSP-2181 и примеры его подключения.

Фирма Analog Devices разработала целые семейства сигнальных процессоров и постоянно продолжает выпускать на рынок новые модели. В настоящее время существуют следующие семейства: ADSP-21XX, Shark DSP, BlackFin DSP и др. Но, несмотря на все многообразие этих групп, все они имеют похожую друг на друга архитектуру. Отличие семейств друг от друга заключается, например, в арифметических блоках, которые поддерживают вычисления с фиксированной или плавающей запятой. Кроме того, семейства отличаются производительностью, разрядностью шин данных, структурой внутренних регистров, интерфейсами и т.п. Отличие процессоров друг от друга внутри семейства состоит в основном в объеме и организации внутренней памяти и типе встроенных интерфейсов. В состав каждого из процессоров этого семейства входят следующие функциональные устройства.

• Арифметико-логическое устройство АЛУ.

• Умножитель-накопитель.

• Устройство сдвига.

• Два генератора адреса данных.

• Программный автомат.

• Таймер.

• Последовательный многоканальный порт.

Ниже приведена табл. 2.1 с отличительными характеристиками сигнальных процессоров семейства ADSP-21XX.

Таблица 2.1. Характеристики сигнальных процессоров семейства ADSP-21XX

Ресурсы 2101 2103 2105 2111 2115 21msp58 2171 2173 2181 2183
Объем оперативной памяти программ (слов) 2K 2K 1K 2K 1K 2K 2K 2K 16K 16K
Объем оперативной памяти данных (слов) 1K 1K 512 1K 512 2K 2K 2K 16K 16K
Второй последовательный порт - - - - - - - - + +
Порт хост-интерфейса - - - + - + + + - -
Порт прямого доступа к памяти - - - - - - - - + +
Максимальная внешняя тактовая частота, МГц 20 10,24 13,82 20 20 16,67 16,67 16,67 20 20
Аналого-цифровые преобразователи и фильтры - - - - - + - - - -
Режим малого потребления - - - - - + + + + +
Напряжение питания, В 5 3,3 5 5 5 5 5 3,3 5 3,3
Количество сигнальных выводов 68 68 68 100 68 100 128 128 128 128

Остановимся на рассмотрении архитектуры одного из самых распространенных на сегодняшний день процессоров семейства ADSP-21XX, а именно на процессоре ADSP-2181. Этот компонент является самым развитым в своем семействе и включает в себя наибольший объем памяти и множество встроенных интерфейсов.

Сигнальный процессор ADSP-2181 представляет собой однокристальный чип, выпускаемый в 128 выводных корпусах типа PQFP-128 или TQFP-128. Из вышеприведенной информации уже можно составить общее представление о возможностях, заложенных в данный процессор. Но для полноты картины рассмотрим структурную схему внутренней архитектуры этого чипа, приведенную на рис. 2.1.

Рис. 2.1. Структурная схема внутренней архитектуры чипа

Процессор имеет сильно развитую структуру внутренних шин адреса и данных. К их числу относятся шина адреса памяти программ PROGRAM MEMORY ADDRESS, шина адреса памяти данных DATA MEMORY ADDRESS, шина данных памяти программ PROGRAM MEMORY DATA и шина данных памяти данных DATA MEMORY DATA.

Слева на схеме изображен базовый блок архитектуры всего семейства ADSP-2100 BASE ARCHITECTURE включаемый в состав любого из процессоров данного семейства. Он состоит из блока генераторов адреса данных DATA ADDRESS GENERATORS, программного автомата PROGRAM SEQUENCER и арифметического блока ARITHMETIC UNITS.

Блок генераторов адреса данных содержит два генератора: DAG1 и DAG2, предназначенных для инвертирования бит адреса во время выполнения процессором операций быстрого преобразования Фурье (БПФ).

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

Арифметический блок включает в себя арифметико-логическое устройство ALU, умножитель с накопителем MAC и устройство сдвига SHIFTER. Первый из этих блоков предназначен для выполнения арифметических и логических операций над данными, а второй для выполнения арифметического умножения чисел. SHIFTER позволяет нормировать числа после выполнения арифметических операций.

Рассмотрим блоки, расположенные справа вверху по схеме. Блок управления пониженным питанием POWER DOWN CONTROL обеспечивает управление процессором для перехода в режим пониженного потребления после выполнения соответствующей инструкции и возврат из этого режима после возникновения прерывания или после перезапуска. Блок памяти MEMORY состоит из памяти данных DATA MEMORY и памяти программ PROGRAM MEMORY. Таким образом, оперативная память всего процессора разделена на две независимых части в соответствии с Гарвардской архитектурой построения процессоров. Тем не менее, система команд этого процессора позволяет использовать память программ для хранения данных. Блок программируемых входов-выходов PROGRAMMABLE I/O позволяет запрограммировать несколько выводов по усмотрению разработчика на ввод или на вывод битовых сигналов, что обеспечивает возможность гибкого применения этих выводов. Блок флагов FLAGS управляет тремя битовыми выводами, организованными как сигнальные выходы. Наконец, блок байтового контроллера прямого доступа к памяти BYTE DMA CONTROLLER, сокращенное и часто употребляемое в дальнейшем название которого BDMA, обеспечивает быстрый аппаратный ввод и вывод байтовых данных через внешнюю шину данных процессора.

Теперь рассмотрим блоки, расположенные справа внизу по схеме. Одним из самых популярных и полезных является блок последовательных многофункциональных портов SERIAL PORTS, который включает в себя два последовательных порта SPORT1 и SPORT2. Отличительной особенностью этих портов является то, что они программируемые, синхронные и многоканальные. Т.е. каждый из этих портов способен принимать и передавать информацию от однословного до тридцатидвухсловного последовательного потока бит. Каждое слово в потоке может иметь длину от трех до шестнадцати бит. Этот формат передачи данных часто применяется при построении телекоммуникационных систем. К такому порту можно подключить одновременно до 32 кодеков и получить на их выходе соответственно 32 аналоговых канала ввода-вывода. Согласитесь — это мощный инструмент, который можно применить во многих областях. Кроме того, порты могут программироваться на внешнюю или внутреннюю синхронизацию. Управляющие выводы портов также могут быть запрограммированы на ввод или вывод.

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

И, наконец, блок внутреннего порта INTERNAL DMA PORT IDMA, сокращенное название которого IDMA, предназначен для организации прямого доступа к памяти данных и памяти программ процессора по шестнадцатиразрядной внешней шине. Этот порт играет важную роль при работе с процессором, поскольку позволяет загружать программу и данные непосредственно в память процессора до его старта, стартовать процессор и производить операции чтения и записи данных в память во время его работы, незначительно влияя при этом на производительность процессора.

С внешним миром процессор общается посредством четырнадцатиразрядной шины адреса EXTERNAL ADDRESS BUS, двадцати четырехразрядной шины данных EXTERNAL DATA BUS и шестнадцатиразрядной шины IDMA DMA BUS.

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

Рис. 2.2. Структурная схема процессора

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

На рис. 2.3 и 2.4 представлены варианты исполнения процессора в корпусах PQFP-128 и TQFP-128, соответственно. На этих же рисунках изображено назначение всех контактов процессора и приведена их нумерация.

Рис. 2.3. Вариант исполнения процессора в корпусе PQFP-128

Рис. 2.4. Вариант исполнения процессора в корпусе TQFP-128

Изображения дают вид сверху TOP VIEW, выводами вниз PINS DOWN. Сигналы с низкими активными уровнями имеют обозначения с чертой над сигналом. Выводы двойного назначения, определяемого программированием этих выводов, обозначаются через символ «/».

В табл. 2.2 дается описание назначения выводов процессора.

Таблица 2.2 Описание выводов процессора ADSP-2181

Наименование Вывод I/O Функция
А0…А13 O Адресные выводы для адресации области внешней памяти программ, памяти данных, байтовой памяти (BDMA) и устройств ввода-вывода
D0…D23 I/O Выводы данных для обмена данными с внешней памятью программ и памятью данных. Восемь старших разрядов также используются как адрес байтовой памяти.
-WR O Сигнал записи
-RD O Сигнал чтения
-IOMS O Выбор области памяти
-BMS O Выбор байтовой памяти
-DMS O Выбор памяти данных
-CMS O Выбор комбинированной памяти
-PMS O Выбор программной памяти
FL0, FL1, FL2 О Выходы-флаги
PF0…PF7 I/O Программируемые выводы
MMAP I Выбор карты памяти процессора
-PWD I Управление потреблением
BMODE I Режим загрузки 0 — ROM, 1 — IDMA
PWDACK O Контроль низкого потребления питания
XTAL I Соединение с кварцем
CLKIN I Внешний генератор, или соединение с кварцем
CLKOUT O Выходная тактовая частота
-RESET I Сброс процессора
-ERESET I Разрешение сброса
-IRQL0 I Потенциальный запрос прерывания 0
-IRQL1 I Потенциальный запрос прерывания 1
-IRQ2 I Динамический или потенциальный запрос прерывания 2
-IRQE I Динамический запрос прерывания
-BR I Внешний запрос шины
-BG O Внешнее предоставление шины
-BGH O Внешнее предоставление шины, подтянутое к питанию
IAD0…IAD15 I/O Шина адреса/данных порта IDMA
-IACK O Подтверждение доступа к порту IDMA
-IWR I Вход записи в порт IDMA
-IRD I Вход чтения из порта IDMA
-IS I Вход выборки порта IDMA
IAL I Вход защелки адреса порта IDMA
DT0 O Передача данных
TFS0 I/O Кадровая синхронизация передачи
RFS0 I/O Кадровая синхронизация приема
DR0 I Прием данных
SCLK0 I/O Программируемый генератор порта 0
DT1/FO O Передача данных, или выходной флаг
TFS1/IRQ1 I/O Кадровая синхронизация передачи, или внешний запрос прерывания 1
RFS1/IRQ0 I/O Кадровая синхронизация приема, или внешний запрос прерывания 0
DR1/FI I Прием данных, или входной флаг
SCLK1 I/O Программируемый генератор порта 1
-EMS Сигналы, используемые только в режиме эмуляции
ЕЕ
ECLK
ELOUTELIN
EINT
-EBR
-EBG
GND Выводы заземления
VDD Выводы питания

Примечание: I — вход, О — выход; минус перед сигналом означает низкий активный уровень сигнала.

Способ подключения к процессору различных периферийных устройств показан на структурной схеме, приведенной на рис. 2.5. В качестве примера, на этой схеме показано, как подключаются следующие устройства:

Внешний генератор или кварцевый резонатор с половинной тактовой частотой процессора 1/2x CLOCK OR CRYSTAL.

Последовательные устройства SERIAL DEVICE, например кодеки.

Системный интерфейс или микроконтроллер SYSTEM INTERFACE OR MICROCONTROLLER.

Байтовая память BYTE MEMORY.

До 2048 периферийных устройств ввода-вывода I/O SPACE PERIPHERALS.

Внешняя память OVERLAY MEMORY.

Рис. 2.5. Способ подключения к процессору различных периферийных устройств

При использовании внешней памяти, допускается подключение двух 8К-словных сегмента памяти программ TWO 8К РМ SEGMENTS и двух 8К-словных сегмента памяти данных TWO 8К DM SEGMENTS.

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

На рис. 2.6 показан способ подключения кварцевого резонатора к сигнальному процессору. Конденсаторы должны иметь номинальную емкость от 22 до 33 пФ, а максимальная частота кварцевого резонатора должна быть вдвое ниже максимальной внутренней частоты процессора, поскольку внутри процессора производится аппаратное умножение внешней задающей тактовой частоты. Эта удвоенная частота выводится на сигнальный вывод CLKOUT процессора. Вместо кварцевого резонатора, для формирования задающей частоты синхронизации можно использовать интегральный генератор, который, однако, несколько дороже резонатора. В этом случае выход генератора необходимо подключить к выводу CLKIN процессора, а вывод XTAL оставить неподключенным.

Рис. 2.6. Способ подключения кварцевого резонатора к сигнальному процессору

Карта памяти процессора изображена в табл. 2.3. На первых двух фрагментах таблицы показаны режимы использования памяти программ. Эти режимы задаются с помощью внутреннего регистра PMOVLAY и подключения внешнего вывода процессора MMAP к нулевому потенциалу или к источнику питания соответственно. При сбросе процессора регистр PMOVLAY обнуляется, и подключается внутренняя память. В процессе выполнения программы содержимое этого регистра можно изменить, и переключить тем самым процессор на использование внешней памяти программ. Адресация памяти приведена в шестнадцатеричном формате записи.

Таблица 2.3. Карта памяти процессора

Параметр Адрес Память программ Адрес Память данных Адрес
8К слов ВНУТРЕННИЕ (PMOVLAY=0, MMAP=0) или 8К слов ВНЕШНИЕ (PMOVLAY=1 или 2, MMAP=0) 0x3FFF … 0x2000 8К слов ВНУТРЕННИЕ (PMOVLAY=0, MMAP=1) 0x3FFF … 0x2000 32 РЕГИСТРА 0x3FFF … 0x3FE0
8160 слов ВНУТРЕННИЕ 0x3FDF … 0x2000
8К слов ВНУТРЕННИЕ 0x1FFF … 0x0000 8К слов ВНЕШНИЕ 0x1FFF … 0x0000 8К слов ВНУТРЕННИЕ (DMOVLAY=0) или 8К слов ВНЕШНИЕ (DMOVLAY=1 или 2) 0x1FFF … 0x0000

Память программ может быть внутренней INTERNAL, т.е. размещенной на кристалле самого процессора, или внешней EXTERNAL, т.е. размещенной во внешних микросхемах памяти. Поскольку память программ организована 24 разрядными словами, суммарный объем внутренней памяти программ процессора может быть равен (8К слов+8К слов) × 3байта = 48 Кбайт.

На последнем фрагменте рисунка приведена карта памяти данных. Ее режим работы, как внешней или внутренней, определяется с помощью внутреннего регистра процессора DMOVLAY, который аналогично регистру PMOVLAY обнуляется при сбросе или включении процессора, обеспечивая тем самым включение режима использования внутренней памяти данных. В самой верхней области памяти данных размещены 32 служебных регистра процессора, которые организованы как память данных. Поэтому память данных усечена по объему на это количество ячеек памяти. Память данных организована шестнадцатиразрядными словами, поэтому суммарный объем внутренней памяти данных процессора составляет (8К слов + 8К слов) × 2байта = 32 Кбайт.

Учитывая разрядность банков памяти программ и памяти данных, суммарная емкость памяти процессора составляет 80 Кбайт. Это довольно большой объем памяти, достаточный для решения многих задач, написанных на языках ассемблера или Си.

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

Глава 3. Практические схемы включения

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

Итак, приступим непосредственно к практике по освоению сигнального процессора. На рис. 3.1 изображена принципиальная схема тестовой платы для изучения процессора и отладки программ. Файл этой схемы, созданный в системе автоматического проектирования PCAD 4.5, записан на компакт-диск, прилагаемый к данной книге. На схеме показан способ включения самого сигнального процессора и периферийных устройств, подключаемых к нему. Рассмотрим последовательно все сигнальные выводы процессора и их назначение.

Рис. 3.1. Принципиальная схема тестовой платы

Рис. 3.1. Принципиальная схема тестовой платы (продолжение)

Рис. 3.1. Принципиальная схема тестовой платы (окончание)

Как видно из схемы, процессор D1 имеет несколько выводов для подключения питания, что связано с необходимостью распределения токоведущих цепей для обеспечения помехоустойчивости. Используемый в схеме сигнальный процессор допускает питание от источника напряжением 4,5…5,5 В. Стабилизированное напряжение питания 5 В поступает с разъема питания XP1. Конденсаторы CP2 и C3–C7 обеспечивают фильтрацию напряжения по низким и высоким частотам соответственно. Индикатор HL4 с токоограничивающим резистором R3 индицирует наличие питания в схеме. Для питания аналоговой части схемы используются дополнительные элементы фильтрации L1 и C8–C10.

Следующими важными цепями являются входы и выходы генераторных сигналов XTAL, CLKIN и CLKOUT. Первые две цепи предназначены для подключения внешнего источника синхронизации. На приведенной схеме показан способ подключения к процессору кварцевого резонатора BQ1. В случае применения интегрального генератора выход генератора подключается к выводу CLKIN, а вывод XTAL не используется. Стоимость генераторов на сегодняшний день еще превышает стоимость кварцевых резонаторов, поэтому к процессору подключен более дешевый кварцевый резонатор. Номинальная резонансная частота такого резонатора или генератора не должна превышать половину предельно допустимой частоты для данного процессора. Так, для процессора с максимальной тактовой частотой 40 МГц она не должна превышать 20 МГц. Конденсаторы C1 и C2 должны быть керамического типа, емкостью от 18 до 30 пФ.

Внутри процессора производится аппаратное умножение внешней частоты, которая затем используется для синхронизации процессора. Внутренняя частота процессора будет составлять 40 МГц, а длительность выполнения команд 25 нс. Внутренняя частота выводится также на CLKOUT процессора и может быть использована для синхронизации других микросхем, подключаемых к процессору.

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

Рис. 3.2. Временная диаграмма сигналов синхронизации

Таблица 3.1 Допустимые параметры сигналов синхронизации процессора

Параметр Минимум Максимум Единица измерения
Сигналы синхронизации
Требуемые длительности:
tCKI 50 150 нс
tCKIL 20 нс
tCKIH 20 нс
Характеристика переключения:
tCKL 0,5tCK-7 нс
tCKH 0,5tCK-7 нс
tCKOH 0 20 нс

tCK= 0,5*tCKI

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

Таблица 3.2 Характеристики сигнальных процессоров

Заводская маркировка Рабочий температурный диапазон, °С Максимальная тактовая частота, МГц Тип корпуса Условное обозначение корпуса
ADSP-2181KST-115 0…+70 28,8 TQFP-128* ST-128
ADSP-2181BST-115 -40…+85 28,8 TQFP-128 ST-128
ADSP-2181KS-115 0…+70 28,8 PQFP-128** S-128
ADSP-2181BS-115 -40…+85 28,8 PQFP-128 S-128
ADSP-2181KST-133 0…+70 33,3 TQFP-128 ST-128
ADSP-2181BST-133 -40…+85 33,3 TQFP-128 ST-128
ADSP-2181KS-133 0…+70 33,3 PQFP-128 S-128
ADSP-2181BS-133 -40…+85 33,3 PQFP-128 S-128
ADSP-2181KST-160 0…+70 40 TQFP-128 ST-128
ADSP-2181 KS-160 0…+70 40 PQFP-128 S-128

* TQFP — Plastic Thin Quad Flatpack (пластиковый тонкий четырехугольный плоский корпус).

** PQFP — Plastic Quad Flatpack (пластиковый четырехугольный плоский корпус).

В нашем случае использован процессор ADSP-2181KS-133 в корпусе PQFP-128, как получивший большое распространение и легко доступный. В табл. 3.3 приведено соответствие выводов корпуса этого процессора его сигналам.

Таблица 3.3 Соответствие выводов корпуса сигналам процессора

Вывод Сигнал Вывод Сигнал Вывод Сигнал Вывод Сигнал
1 PF0 33 PWD 65 EBR 97 D23
2 WR 34 IRQ2 66 BR 98 GND
3 RD 35 BMODE 67 EBG 99 IWR
4 IOMS 36 PWDACK 68 BG 100 IRD
5 BMS 37 IACK 69 VDD 101 IAD15
6 DMS 38 BGH 70 DO 102 IAD14
7 CMS 39 VDD 71 D1 103 IAD13
8 GND 40 GND 72 D2 104 IAD12
9 VDD 41 IRQL0 73 D3 105 IAD11
10 PMS 42 IRQL1 74 D4 106 IAD10
11 А0 43 FLO 75 GND 107 IAD9
12 A1 44 FL1 76 D5 108 IAD8
13 A2 45 FL2 77 D6 109 IAD7
14 A3 46 DT0 78 D7 110 IAD6
15 A4 47 TFS0 79 D8 111 VDD
16 A5 48 RFS0 80 D9 112 GND
17 A6 49 DR0 81 D10 113 IAD5
18 A7 50 SCLK0 82 D11 114 IAD4
19 XTAL 51 DT1/FO 83 D12 115 IAD3
20 CLKIN 52 TFS1/IRQ1 84 D13 116 IAD2
21 GND 53 RFS1/IRQ0 85 D14 117 IAD1
22 CLKOUT 54 GND 86 GND 118 IAD0
23 GND 55 DR1/FI 87 VDD 119 PF7
24 VDD 56 SCLK1 88 GND 120 PF6
25 A8 57 ERESET 89 D15 121 PF5
26 A9 58 RESET 90 D16 122 PF4
27 A10 59 EMS 91 D17 123 GND
28 A11 60 ЕЕ 92 D18 124 IS
29 A12 61 ECLK 93 D19 125 IAL
30 А13 62 ELOUT 94 D20 126 PF3
31 IRQE 63 ELIN 95 D21 127 PF2
32 MMAP 64 EINT 96 D22 128 PF1

Сигнал -RESET обеспечивает сброс процессора в исходное состояние. Этот сигнал должен находиться в активном низкоуровневом состоянии при включении и перезагрузке процессора в течение не менее пяти тактовых периодов внешней синхронизации процессора. Обычно для надежного сброса процессора этот сигнал удерживается в активном состоянии не менее нескольких микросекунд. Формирование сигнала сброса в схеме возможно от любого из двух источников. Первый источник этого сигнала реализован на зарядной цепочке R1, CP1. В момент подачи питания на схему, конденсатор CP1 разряжен и на нем удерживается низкий потенциал в течении времени его заряда, достаточного для приведения процессора в исходное состояние. Диод VD1 обеспечивает быстрый разряд этого конденсатора в момент отключения или кратковременного пропадания питания. Кнопка SB4 предназначена для принудительного сброса процессора вручную. Резистор R2 ограничивает ток разряда, предохраняя контакты кнопки от образования искр, и устраняет дребезг контактов совместно с конденсатором CP1. Вторым источником сигнала сброса является сигнал — RESI с разъема XU1, который буферизуется шинным повторителем D4.1 и поступает на микросхему D6. С помощью элементов D6.3 и D6.4 оба сигнала объединяются в один сигнал сброса процессора в инверсном (-RESET) и неинверсном виде (RESET). Наличие неинверсного сигнала требуется для сброса других микросхем с активным высокоуровневым входом сброса.

Сигнал -ERESET и сигналы на выводах 59…65 и 67 процессора предназначены для подключения к нему специального аппаратного эмулятора EZ-ICE, который можно приобрести через представителей фирмы Analog Device в России. Выводы эмулятора подключены к разъему XEZ в соответствии с рекомендациями по применению данного сигнального процессора. Однако на практике вполне можно обходиться и без этого эмулятора.

Следующая группа сигналов -IRQL0, -IRQL1, -IRQ2 и -IRQE отвечает за передачу процессору внешних прерываний. В качестве источников прерываний могут выступать различные микросхемы, датчики, кнопки и т.п. Так, к сигнальному выводу -IRQE подключена кнопка SB5 через цепочку устранения дребезга контактов R22 и CP4. Резистор R23 предназначен для удержания сигнала прерывания в пассивном состоянии. В дальнейшем с ее помощью можно будет принудительно вызывать прерывание процессора при необходимости.

Следующие три сигнала обеспечивают запрос и предоставление внешней шины процессора другим внешним устройствам. На схеме сигнал запроса шины -BR используется только при подключении к схеме эмулятора EZ-ICE и подключен к разъему XEZ. Этот сигнал подтянут к шине питания для приведения его в пассивное состояние. Выходной сигнал -BG, подтверждающий предоставление шины процессором, также подключен к разъему XEZ. Сигнал -BGH не используется и остается не подключенным.

Далее следует группа важных сигналов порта прямого доступа к памяти процессора. Это шестнадцать мультиплексированных сигналов шины адреса данных IAD0–IAD15 и сигналы управления IACK, -IWR, -IRD, -IS, IAL. Данный порт можно использовать для загрузки программ и данных во внутреннюю память процессора и, кроме того, читать содержимое памяти процессора во время его работы. Это позволяет обходиться без эмулятора EZ-ICE, облегчает отладку программ и дает большую гибкость при разработке многопроцессорных схем. На схеме все эти сигналы подключены через буферные микросхемы D2, D3, D4.1, D5.1, D5.5 и D5.5 к внешнему разъему XU1. В дальнейшем мы рассмотрим специальный адаптер, который позволит нам оперативно загружать программы в процессор, читать и записывать данные в его память и окажет большую помощь в изучении самого процессора и освоении его системы команд и способов программирования. Цепочка элементов R4 и C11 фильтрует высокочастотные импульсы, проникающие на чувствительный вход IAL процессора, обеспечивая тем самым повышенную помехозащищенность. Резисторные сборки RN1 и RN2 подтягивают сигналы порта IDMA и прерываний к высокому пассивному уровню.

Следующие две группы сигналов последовательных портов SPORT0 и SPORT1 обеспечивают работу с последовательными устройствами. К порту SPORT0 в схеме подключен кодек DA1 типа MC14LC5480, который содержит в себе кодер и декодер с фильтрами и компандер. В отличие от аналого-цифрового и цифро-аналогового преобразователей, он отличается тем, что выполняет преобразование сигналов по А-типу или μ-типу. Фактически оба эти типа преобразования являются аппроксимацией логарифмической функции с различной степенью приближения. Они активно применяются в телекоммуникационных системах для цифрового преобразования и сжатия информации с максимальным сохранением соотношения сигнал-шум. Для этого аналоговые сигналы малой амплитуды дискретизируются чаще. Для сжатия цифровой информации используется функция компандирования, встроенная в кодек и сигнальный процессор. С помощью этой функции производится прямое и обратное преобразование 13- или 14-разрядных слов в 8-разрядные, за счет нелинейного прореживания. В цифровых каналах связи используются именно такие 8-битные данные. Для нормальной работы кодеку необходимы сигналы синхронизации и кадровые стробы приемника и передатчика. Эти сигналы формируются портом SPORT0 на выводах SCLK0, RFS0 и TFS0 соответственно. Все перечисленные сигналы синхронизации и стробов программируются в процессоре по направлению, частоте, длительности и фазовому сдвигу. Цифровые данные приемника и передатчика порта транслируются на кодек по сигнальным выводам DR0 и DT0 соответственно. Помимо перечисленных узлов, кодек содержит в себе операционные усилители и источник опорного напряжения для смещения напряжения на входах усилителей относительно нулевого потенциала. Аналоговый сигнал на кодек заведен с разъема XIN типа тюльпан, через развязывающий конденсатор C16.

Стабилитроны VS1 и VS2 защищают вход кодека от сигналов большой амплитуды. Резисторы R9 и R10 определяют коэффициент усиления входного сигнала. Опорное напряжение подведено к неинверсному входу кодека через резистор R12. Цепочка R11-C17 корректирует смещение по высоким частотам. Конденсатор C18 является фильтрующим. Оцифрованный сигнал поступает в процессор на вход DR0 для обработки или цифровой записи. В свою очередь, процессор посылает в кодек цифровые сигналы для последующего их преобразования в аналоговый сигнал. После цифро-аналогового преобразования сигнала DT0 от процессора выходной аналоговый сигнал с кодека поступает через ограничительный резистор R14 на разъем XOUT. Кроме того, этот же сигнал поступает на низкочастотный усилитель, выполненный на транзисторах VT1 и VT2. В нагрузку усилителя, через развязывающий конденсатор CR3, включена миниатюрная динамическая головка BA1. Она позволит прослушивать сигналы, генерируемые процессором через кодек. Резисторы R13 и R16 определяют коэффициент усиления всего каскада, а резистор R15 обеспечивает необходимое смещение на базах транзисторов.

Выводы порта SPORT1 являются многофункциональными. Они могут быть запрограммированы как на работу с последовательными устройствами подобно порту SPORT0, так и в альтернативном режиме как флаги входа-выхода и входы прерывания. В нашей схеме используется второй способ их применения. Вывод 51 порта будет работать как выход, а вывод 55 как вход. Кроме того, задействован вход прерывания IRQ1, для формирования прерывания процессора при поступлении информации по сигнальному выводу FI. Эти выводы задействованы для организации последовательного порта RS-232 или проще — компьютерного СОМ порта. Для этого они подключены к микросхеме преобразования уровней DA2. Эта микросхема преобразует ТТЛ уровни сигнала в уровни стандарта RS-232. Конденсаторы C12–C15 обеспечивают работу внутренних умножителей напряжения в микросхеме. Сигналы порта RS-232 выведены на девятиштырьковый разъем XRS1. Назначение сигналов на этом разъеме соответствует стандарту, принятому для персональных компьютеров IBM PC. В дальнейшем к этому порту можно подключить компьютер, с помощью нуль-модемного кабеля, для загрузки обучающих программ с помощью программного пакета EZ-KIT Lite, распространяемого фирмой Analog Device.

Сигналы А0–А13 являются адресными и предназначены для адресации внешней памяти или устройств ввода-вывода. В схеме они подключены к адресным выводам микросхемы постоянной памяти D7, а некоторые из них, к дешифратору устройств ввода-вывода D9.

Сигналы D0–D23 предназначены для передачи данных и для адресации. Младшие восемь бит этой шины участвуют в обмене данными только с расширенной памятью. В нашей схеме эта память не подключена и, соответственно, сигналы D0–D7 не задействованы. Разряды D8–D15 используются для передачи данных при обращении к байтовой памяти BDMA.

В нашей схеме эту роль выполняет микросхема постоянной флэш-памяти D7. Наконец, старшие разряды этой шины D16–D23 выполняют двоякую роль. При обращении к байтовой памяти они несут функцию старших адресных линий, а при обращении к устройствам ввода-вывода являются старшими разрядами шины данных.

Далее следуют сигналы записи -WR, чтения -RD и выборки внешних устройств. В нашей схеме из внешних устройств будет использоваться байтовая память D7, выбираемая сигналом -BMS с помощью дешифратора D8, и устройства ввода-вывода, выбираемые сигналом -IOMS с помощью дешифратора D9 и логических элементов D13.1, D13.2. В схеме присутствует восьмиразрядный регистр ввода D11 и восьмиразрядный регистр вывода D12. Первый из них позволяет снимать дискретные сигналы с различных цифровых датчиков, контактов и пр. А второй обеспечивает возможность управления цифровыми ключами, индикаторами и т.п. Выводы этих регистров заведены на разъемы XI и ХО соответственно.

Временные диаграммы циклов чтения и записи данных процессором, представлены на рис. 3.3 и 3.4, соответственно. Параметры сигналов для этих циклов приводятся в табл. 3.4 и 3.5.

Рис. 3.3. Временная диаграмма цикла чтения

Рис. 3.4. Временная диаграмма цикла записи

Таблица 3.4 Параметры сигналов для цикла чтения данных процессором

Параметр Минимум Максимум Единица измерения
Чтение памяти
Требуемые длительности:
tRDD 0,5 tCK - 9 + w нс
tAA 0,25 tCK - 10.5 + w нс
tRDH 0 нс
Характеристика переключения:
tRP 0,5 tCK - 5 + w 0,25 tCK + 7 нс
tCRD 0,25 tCK - 5 нс
tASR 0,25 tCK - 6 нс
tRDA 0,25 tСK - 3 нс
tRWR 0,5 tCK - 5 нс

Таблица 3.5 Параметры сигналов для цикла записи данных процессором

Параметр Минимум Максимум Единица измерения
Запись памяти
Характеристика переключения:
tDW 0,5 tСK - 7 + w нс
tDH 0,25 tСK - 2 нс
tWP 0,5 tCK - 5 + w нс
tWDE 0 нс
tASW 0,25 tCK - 6 нс
tDDR 0,25 tCK - 7 нс
tCWR 0,25 tCK - 5 нс
tAW 0,75 tCK - 9 + w 0,25 tСK + 7 нс
tWRA 0,25 tCK - 3 нс
tWWR 0,5 tCK - 5 нс

* w — число циклов задержки * tCK

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

Следующая группа сигналов FL0-FL2 является битовыми выходными сигналами, которые работают только на вывод. К ним подключены индикаторы HL0-HL2 через буферный повторитель D4.2.

В отличие от FL0-FL2, выводы PF0-PF7 являются двунаправленными битовыми сигналами и могут быть запрограммированы как на ввод, так и на вывод побитно. Так, к выводу PF7 подключен индикатор HL3, а выводы PF0-PF3 будут запрограммированы как входы и к ним подключены кнопки SB0-SB3. Резисторы R5–R8 являются токоограничивающими, а резисторная сборка RN3 подтягивает сигналы управления и входные сигналы к высокому уровню.

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

Сигнал -PWD отвечает за формирование немаскируемого прерывания при снижении питания процессора ниже нормы. Для его использования необходимо подключить к нему выход узла, отслеживающего напряжение питания и формирующего потенциал низкого уровня для формирования прерывания при снижении напряжения питания ниже установленной границы. В результате процессор успевает сохранить необходимые данные в энергонезависимой внешней памяти или выполнить другие необходимые инструкции для предотвращения неблагоприятных последствий, связанных с пропаданием питания. В нашей схеме данный сигнал подключен непосредственно к плюсовому выводу шины питания и не используется. Также не используется и выходной сигнал PWDACK, предназначенный для транзита сигнала, уведомляющего о снижении питания.

Наконец последний вывод процессора BMODE определяет интерфейс, через который будет производиться загрузка процессора. Если на этот вывод подан нулевой потенциал, загрузка процессора будет производиться через интерфейс BDMA, т.е. из байтовой памяти. В противном случае процедура загрузки будет производиться через интерфейс IDMA. В дальнейшем мы рассмотрим оба варианта загрузки. Для автоматизации процесса загрузки в схеме применен триггер, выполненный на элементах D4.1 и D4.2. В зависимости от источника сброса, триггер переключается в такое состояние, которое обеспечивает установку на выводе BMODE сигнала, необходимого для загрузки через соответствующий интерфейс.

Еще одно внешнее устройство в качестве дополнения схемы приведено на рис. 3.5. Это дополнение схемы не является обязательным и может не распаиваться на основную плату. Но если появится необходимость оснащения рассмотренной выше схемы еще одним последовательным портом типа RS-422, это дополнение поможет в этом.

Рис. 3.5. Внешнее устройство в качестве дополнения схемы процессора

Как видно из рисунка, схема содержит интегрированную микросхему UART D12 с подключенными к ней резонатором BQ2 и вспомогательными конденсаторами C19, C20 для запуска внутреннего генератора. Программирование этой микросхемы производится через сигналы шины данных DD0–DD7. Выходные сигналы микросхемы UART подключены к приемопередатчикам — преобразователям уровней сигналов DA3 и DA4 для организации последовательного порта RS-422. Элементы D5.2 и D5.3 инвертируют выходные сигналы управления UART, обеспечивая отключение приемопередатчиков DA3 и DA4 в момент сброса самого UART или при включении.

Элемент D5.3 инвертирует выходной сигнал запроса прерывания от UART. Резисторы R17–R21 обеспечивают пассивное состояние сигналов при отключенной линии связи. Этот порт позволяет обмениваться информацией со 127 другими устройствами по аналогичному порту на расстоянии до 1200 метров. Все сигналы порта выведены на разъем XRS2.

Вся схема может быть распаяна на небольшой макетной плате или на специально изготовленной плате с разработанной топологией электрических соединений. Для разработки топологии печатной платы необходимо создать файл посадочного места для компонента — процессора, который будет использоваться системой автоматического проектирования САПР. Чертеж корпуса процессора приведен на рис. 3.6.

Рис. 3.6. Корпус процессора

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

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

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

Глава 4. Программно-логическая модель

В этой главе говорится о внутренней программно-логической модели процессора и его системе прерываний.

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

Итак, начнем с программно-логической модели процессора. Такая модель для ADSP-2181 приведена на рис. 4.1.

Рис. 4.1. Программно-логическая модель ADSP-2181

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

Главный блок регистров представлен на рисунке слева, в процессорном ядре. В первую очередь это блоки регистров программных генераторов адреса DAG1 и DAG2. Данные блоки регистров включают в себя индексные регистры I, регистры длины буфера L и регистры-модификаторы M.

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

Блок программного автомата содержит регистры, отвечающие за автоматические операции процессора. В их число входят:

• программный счетчик с 16-уровневым 14-разрядным стеком PC STACK, для организации вызова подпрограмм и обработки прерываний;

• счетчик циклов CNTR с 4-уровневым 14-разрядным стеком COUNT STACK, для организации вложенных программных циклов;

• псевдорегистр OWRCNTR, для обновления значения счетчика CNTR;

• цикловой компаратор LOOP STACK с 4-уровневым 18-разрядным стеком, для обеспечения выполнения программных циклов без тактов ожидания.

Назначение остальных регистров управления и состояния блока программного автомата процессора, приводится в табл. 4.1. Обращение к этим регистрам из программы производится по их логическим именам, совпадающим с именами, приведенными на рис. 4.1 и в табл. 4.1.

Таблица 4.1а Регистр состояния арифметико-логического устройства ASTAT

Разряд Исходное состояние Назначение
7 0 Флаг знака ввода в устройство сдвига SHIFTER (SS)
6 0 Флаг переполнения в умножителе-накопителе MAC (MV)
5 0 Флаг частного АЛУ (AQ)
4 0 Флаг знака ввода порта X в АЛУ (AS)
3 0 Флаг переноса бита в АЛУ (АС)
2 0 Флаг переполнения АЛУ (AV)
1 0 Флаг отрицательного результата в АЛУ (AN)
0 0 Флаг нулевого значения в АЛУ (AZ)

Таблица 4.1б Регистр состояния режима процессора MSTAT

Разряд Исходное состояние Назначение
6 0 Разрешение режима GO
5 0 Разрешение работы таймера
4 0 Результаты умножителя: 0 — дробные, 1 — целые
3 0 Разрешение режима насыщения регистра AR АЛУ
2 0 Разрешение режима фиксации переполнения АЛУ
1 0 Разрешение бит-реверсивной адресации DAG1
0 0 Выбор банка регистров данных: 0 — главный, 1 — теневой

Таблица 4.1в Регистр разрешения прерываний IMASK (0 — запрещено, 1 — разрешено)

Разряд Исходное состояние Назначение
15…10 0 Не используются
9 0 -IRQ2
8 0 -IRQL1
7 0 -IRQL0
6 0 Передатчик SPORT0
5 0 Приемник SPORT0
4 0 -IRQE
3 0 BDMA
2 0 Передатчик SPORT1 или -IRQ1
1 0 Приемник SPORT0 или -IRQ0
0 0 Таймер

Таблица 4.1г Регистр состояния стека SSTAT

Разряд Исходное состояние Назначение
7 0 Стек циклов переполнен
6 1 Стек циклов пуст
5 0 Стек состояний переполнен
4 1 Стек состояний пуст
3 0 Стек счетчика переполнен
2 1 Стек счетчика пуст
1 0 Стек счетчика команд переполнен
0 1 Стек счетчика команд пуст

Таблица 4.1д Регистр управления прерываниями ICNTL

Разряд Исходное состояние Назначение
4 X Вложенность прерываний: 0 — запрещена, 1 — разрешена
3 0 Не используется
2 X Чувствительность -IRQ2: 0 — уровень, 1 — фронт
1 X Чувствительность -IRQ1: 0 — уровень, 1 — фронт
0 X Чувствительность -IRQ0: 0 — уровень, 1 — фронт

Таблица 4.1е Регистр установки и сброса прерываний IFC (только запись)

Разряд Исходное состояние Назначение
15 0 Принудительная установка прерывания -IRQ2
14 0 Принудительная установка прерывания передатчика SPORT0
13 0 Принудительная установка прерывания приемника SPORT0
12 0 Принудительная установка прерывания -IRQE
11 0 Принудительная установка прерывания BDMA
10 0 Принудительная установка прерывания передатчика SPORT1 или -IRQ1
9 0 Принудительная установка прерывания приемника SPORT0 или -IRQ0
8 0 Принудительная установка прерывания таймера
7 0 Сброс прерывания -IRQ2
6 0 Сброс прерывания передатчика SPORT0
5 0 Сброс прерывания приемника SPORT0
4 0 Сброс прерывания -IRQE
3 0 Сброс прерывания BDMA
2 0 Сброс прерывания передатчика SPORT1 или -IRQ1
1 0 Сброс прерывания приемника SPORT0 или -IRQ0
0 0 Сброс прерывания таймера

X — произвольное состояние после сброса.

Блок арифметико-логического устройства ALU включает в себя:

• два 16-разрядных регистра операндов AX0 и AX1;

• два 16-разрядных регистра операндов AY0 и AY1;

• один 16-разрядный регистр результата AR;

• один 16-разрядный регистр обратной связи AF.

Все эти регистры имеют своих двойников — теневые регистры, изображенные на рисунке программно-логической модели процессора в виде теней. Переключение между основными и теневыми регистрами производится программно. Блок умножителя MAC включает в себя:

• два 16-разрядных регистра операндов MX0 и MX1;

• два 16-разрядных регистра операндов MY0 и MY1;

• два 16-разрядных регистра результата MR0 и MR1;

• один 8-разрядный регистра результата MR2;

• один 16-разрядный регистр обратной связи AMF.

Блок устройства сдвига SHIFTER включает в себя:

• два 16-разрядных регистра результата SR0 и SR1;

• один 5-разрядный регистр блочных операций SB;

• один 8-разрядный регистр экспоненты SE;

• один 16-разрядный регистр операнда SI.

Так же как и в ALU, в блоках MAC и SHIFTER все регистры имеют своих двойников — теневые регистры.

Устройство обмена между шинами представляет собой 8-разрядный регистр PX, участвующий в пересылках между шинами адреса и данных.

Остальные регистры процессора распределены между блоками таймера, интерфейсной памяти, портов SPORT0 и SPORT1, портов IDMA и BDMA и блоком программируемых флагов.

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

Всего в процессоре отведено тридцать две ячейки 16-разрядных слов с адреса 0x3FE0 по адрес 0x3FFF для регистров такого типа. Часть ячеек памяти для таких регистров не используется в рассматриваемом процессоре ADSP-2181, но используется в других процессорах семейства ADSP-21XX.

В табл. 4.2 приведено назначение разрядов всех регистров, отображенных на память процессора.

Таблица 4.2а Регистр управления системой SCR, адрес памяти данных = 0x3FFF

Разряд Исходное состояние Назначение
15…13 0 Не используются
12 0 Разрешение порта SPORT0: 0=порт запрещен, 1=порт разрешен
11 0 Разрешение порта SPORT1: 0=порт запрещен, 1=порт разрешен
10 0 Конфигурация режима работы порта SPORT1: 0=сигналы FI FO IRQ0 IRQ1 SCLK, 1=последовательный порт SPORT1
9…3 0 Не используются
2…0 1 Циклы ожидания памяти программ от 0 до 7

Таблица 4.2б Регистр тактов ожидания WSR, адрес памяти данных=0x3FFE

Разряд Исходное состояние Назначение
15 0 Не используется
14…12 1 Циклы ожидания памяти данных от 0 до 7
11…9 1 Циклы ожидания 3-й группы портов ввода-вывода от 0 до 7
8…6 1 Циклы ожидания 2-й группы портов ввода-вывода от 0 до 7
5…3 1 Циклы ожидания 1-й группы портов ввода-вывода от 0 до 7
2…0 1 Циклы ожидания 0-й группы портов ввода-вывода от 0 до 7

Таблица 4.2в Регистры таймера

Разряд Исходное состояние Назначение
Регистр периода таймера TPERIOD, адрес памяти данных=0x3FFD
15…0 X Период таймера от 0 до 0xFFFF
Регистр счетчика таймера TCOUNT, адрес памяти данных=0x3FFC
15…0 X Счетчик таймера от 0 до 0xFFFF
Регистр масштабирования таймера TSCALE, адрес памяти данных=0x3FFB
15…8 0 Не используются
7…0 X Масштабирование таймера от 0 до 0xFF

Таблица 4.2г Регистры последовательного порта SPORT0

Разряд Исходное состояние Назначение
Регистр разрешения многоканального приема S0RW1, адрес памяти данных = 0x3FFA
15…0 X Разрешение приема канала 31…16
Регистр разрешения многоканального приема S0RW0, адрес памяти данных = 0x3FF9
15…0 X Разрешение приема канала 15…0
Регистр разрешения многоканальной передачи S0TW1, адрес памяти данных=0x3FF8
15…0 X Разрешение передачи канала 31…16
Регистр разрешения многоканальной передачи S0TW0, адрес памяти данных=0x3FF7
15…0 X Разрешение передачи канала 15…0
Регистр управления S0CR, адрес памяти данных=0x3FF6
15 0 Разрешение многоканальности: 0 — запрещено, 1 — разрешено
14 0 Разрешение внутреннего тактового генератора: 0 — запрещен, 1 — разрешен
13 0 Требование кадровой синхронизации приема: 0 — не требуется, 1 — требуется (в многоканальном режиме — задержка)
12 0 Требование широкого кадрового импульса приемника: 0 — не требуется, 1 — требуется (в многоканальном режиме — задержка)
11 0 Требование кадровой синхронизации передатчика: 0 — не требуется, 1 — требуется (в многоканальном режиме — задержка)
10 0 Требование широкого кадрового импульса передатчика: 0 — не требуется, 1 — требуется (в многоканальном режиме — задержка)
9 0 Разрешение внутреннего тактового генератора передатчика: 0 — запрещен, 1 — разрешен (в многоканальном режиме — число каналов: 0 — 24 канала, 1 — 32 канала)
8 0 Разрешение внутреннего кадрового генератора приемника: 0 — запрещено, 1 — разрешено
7 0 Разрешение инвертирования кадрового генератора передатчика: 0 — запрещено, 1 — разрешено (только в многоканальном режиме)
6 0 Разрешение инвертирования кадрового генератора приемника: 0 — запрещено, 1 — разрешено
5, 4 0 Формат данных: 00 — выравнивание по правому краю, старшие биты=0, 01 — выравнивание по правому краю, старшие биты=знаку, 10 — компандирование по МЮ закону, 11 — компандирование по А закону
3…0 0 Длина слова минус 1
Регистр делителя тактовых импульсов S0CLKDIV, адрес памяти данных = 0x3FF5
15…0 0 Делитель частоты тактовых импульсов = (CLKOUT/2*SCLK)-1
Регистр делителя кадровых импульсов приемника S0RFDIV, адрес памяти данных=0x3FF4
15...0 0 Делитель частоты тактовых импульсов = (SCLK/RFS)-1
Регистр управления авто буферизацией S0ABUF, адрес памяти данных = 0x3FF3
15 0 Не используется
14 0 Бит разрешения CLKOUT
13 0 Не используется
12 0 Бит управления округлением со смещением
11…9 0 Номер индексного регистра передатчика
8, 7 0 Номер регистра модификатора передатчика
6…4 0 Номер индексного регистра приемника
3, 2 0 Номер регистра модификатора приемника
1 0 Разрешение автобуферизации передатчика
0 0 Разрешение автобуферизации приемника

Таблица 4.2д Регистры последовательного порта SPORT1

Разряд Исходное состояние Назначение
Регистр управления S1CR, адрес памяти данных=0x3FF2
15 0 Флаг FO (только чтение)
14 0 Разрешение внутреннего тактового генератора: 0 — запрещен, 1 — разрешен
13 0 Требование кадровой синхронизации приема: 0 — не требуется, 1 — требуется
12 0 Требование широкого кадрового импульса приемника: 0 — не требуется, 1 — требуется
11 0 Требование кадровой синхронизации передатчика: 0 — не требуется, 1 — требуется
10 0 Требование широкого кадрового импульса передатчика: 0 — не требуется, 1 — требуется
9 0 Разрешение внутреннего тактового генератора передатчика: 0 — запрещен, 1 — разрешен
8 0 Разрешение внутреннего кадрового генератора приемника: 0 — запрещено, 1 — разрешено
7 0 Разрешение инвертирования кадрового генератора передатчика: 0 — запрещено, 1 — разрешено
6 0 Разрешение инвертирования кадрового генератора приемника: 0 — запрещено, 1 — разрешено
5, 4 0 Формат данных: 00 — выравнивание по правому краю, старшие биты=0, 01 — выравнивание по правому краю, старшие биты=знаку, 10 — компандирование по МЮ закону, 11 — компандирование по А закону
3…0 0 Длина слова минус 1
Регистр делителя тактовых импульсов S1CLKDIV, адрес памяти данных=0x3FF1
15…0 0 Делитель частоты тактовых импульсов = (CLKOUT/2*SCLK)-1
Регистр делителя кадровых импульсов приемника S1RFDIV, адрес памяти данных=0x3FF0
15…0 0 Делитель частоты тактовых импульсов = (SCLK/RFS)-1
Регистр управления автобуферизацией S1ABUF, адрес памяти данных=0x3FEF
15 0 Блокирование вывода XTAL в режиме пониженной мощности: 0 — активен, 1 — блокирован (этот вывод должен быть блокирован, если к процессору подключен генератор, а не кварцевый резонатор)
14 0 Разрешение задержки запуска процессора из режима пониженной мощности на 4096 циклов: 0 — запрещено, 1 — разрешено
13 0 Принудительный вход в режим пониженной мощности: 0 — нормальный режим, 1 — режим пониженной мощности (осуществляется переход на вектор прерывания пониженной мощности)
12 0 Принудительный перезапуск процессора при подаче питания: 0 — нормальный режим, 1 — программный перезапуск
11…9 0 Номер индексного регистра передатчика
8, 7 0 Номер регистра модификатора передатчика
6…4 0 Номер индексного регистра приемника
3, 2 0 Номер регистра модификатора приемника
1 0 Разрешение автобуферизации передатчика
0 0 Разрешение автобуферизации приемника

Таблица 4.2е Регистры управления программируемыми флагами

Разряд Исходное состояние Назначение
Регистр управления программируемыми флагами PFTYPE, адрес памяти данных=0x3FE6
15 0 Не используется
14…12 1 Циклы ожидания байтовой памяти данных BDMA от 0 до 7
11 1 Разрешение выборки портов ввода-вывода сигналом -CMS: 0 — запрещено, 1 — разрешено
10 0 Разрешение выборки байтовой памяти данных BDMA сигналом -CMS: 0 — запрещено, 1 — разрешено
9 1 Разрешение выборки памяти данных сигналом -CMS: 0 — запрещено, 1 — разрешено
8 1 Разрешение выборки памяти программ сигналом -CMS: 0 — запрещено, 1 — разрешено
7…0 0 Режим работы программируемых выводов флагов PF7…PF0: 0 — выход, 1 — вход
Регистр управления программируемыми флагами PFDATA, адрес памяти данных=0x3FE5
15…8 X Не используются
7…0 X Данные программируемых выводов флагов PF7…PF0 (чтение/запись)

Таблица 4.2ж Регистры управления портом байтовой памяти BDMA

Разряд Исходное состояние Назначение
Регистр-счетчик слов BWCOUNT, адрес памяти данных=0x3FE4
15, 14 0 Не используются
14…0 0x20/0 Значение счетчика (когда MMAP=0 и BMODE=0 значение счетчика = 0x20, когда MMAP=1 или BMODE=1 значение счетчика = 0)
Регистр управления BDMACR, адрес памяти данных = 0x3FE3
15…8 0 Номер страницы BDMA от 0 до 0xFFFF
7…4 0 Не используются
3 1 Режим работы процессора при выполнении циклов BDMA: 0 — работа, 1 — останов
2 0 Направление передачи данных: 0 — чтение из BDMA, 1 — запись в BDMA
1, 0 0 Тип данных: 00 — память программ 24 разрядов, 01 — память данных 16 разрядов, 10 — память данных 8 старших разрядов, 11 — память данных 8 младших разрядов
Регистр внешнего адреса BEAD, адрес памяти данных = 0x3FE2
15, 14 0 Не используются
13…0 0 Значение внешнего адреса на шине процессора, при обмене через BDMA (от 0 до 0x3FFF)
Регистр внутреннего адреса BIAD, адрес памяти данных = 0x3FE1
15, 14 0 Не используются
13…0 0 Значение внутреннего адреса памяти процессора при обмене через BDMA (от 0 до 0x3FFF)

Таблица 4.2з Регистр управления IDMACR

Разряд Исходное состояние Назначение
15 0 Не используется
14 0 Указатель типа памяти: 0 = память программ РМ, 1 = память данных DM
13...0 0 Значение начального адреса памяти процессора при обмене через IDMA (от 0 до 0x3FFF)

X — произвольное состояние после сброса.

Условные обозначения регистров в таблицах соответствуют их названиям на программно-логической модели, изображенной на рис. 4.1.

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

Глава 5. Система прерываний

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

Диспетчер прерываний позволяет процессору реагировать на одиннадцать возможных прерываний и сброс. Все векторы прерываний процессора ADSP-2181 представлены в табл. 5.1.

Таблица 5.1 Векторы прерываний сигнального процессора ADSP-2181

Приоритет Источник прерывания Адрес (HEX)
Высший приоритет 0 Сброс (или выход из режима пониженной мощности при установке 12-го разряда регистра S1ABUF=1) 0000
1 Снижение потребляемой мощности (немаскируемое прерывание) 002C
2 IRQ2 0004
3 IRQL1 0008
4 IRQL0 000C
5 SPORT0 Передатчик 0010
6 SPORT0 Приемник 0014
7 IRQE 0018
8 BDMA прерывание 001C
9 SPORT1 Передатчик или IRQ1 0020
10 SPORT1 Приемник или IRQ0 0024
11 Низший приоритет Таймер 0028

Прерывания в процессоре имеют различную приоритетность, от 0 до 11. При возникновении любого из прерываний, процессор выполняет переход на подпрограмму обработки соответствующего прерывания, адрес которой заложен в векторе данного прерывания. Адреса векторов прерываний расположены в самом начале программной памяти процессора через четыре 24-разрядных слова команды, что позволяет производить простую обработку или выход из прерывания на месте, без перехода на подпрограмму обработчика прерывания. В противном случае может быть выполнен безусловный переход на подпрограмму обработчика прерывания командой jump.

Процессор ADSP-2181 имеет четыре вывода для поддержки внешних прерываний: IRQ2, IRQL0, IRQL1 и IRQE. Кроме того, благодаря возможности SPORT1 быть переконфигурированным на выводы флагов FLAG_IN, FLAG_OUT и прерываний IRQ0, IRQ1, процессор может иметь еще два входа внешних прерываний вместо внутренних прерываний SPORT1. В результате, в общей сложности процессор может иметь шесть внешних прерываний.

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

Все прерывания, кроме немаскируемого и сброса, можно запретить с помощью регистра IMASK (см. табл.1). Кроме того, можно программно сгенерировать или сбросить некоторые прерывания с помощью регистра IFC.

Процессор реагирует на уровень сигналов на выводах прерываний IRQL0 и IRQL1. Прерывание IRQE возникает по фронту изменения сигнала на этом выводе. Чувствительность процессора к сигналам IRQ0, IRQ1 и IRQ2 определяется программно, с помощью регистра ICNTL.

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

Часть II. Программирование

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

Глава 6. Первая программа

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

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

Введите текст этой программы в компьютер с помощью любого текстового редактора и сохраните в файле с именем mem_clr.dsp или скопируйте с компакт-диска, прилагаемого к данной книге.

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

/* Программа mem_clr загружается в память программ и после */

/* запуска заполняет память данных сигнального процессора  */

/* с адреса 0x0000 по адрес 0x3fdf числовыми значениями    */

/*                                                         */

/* Версия: 1.0                                             */

/* Автор:  О.Д.Вальпа                                      */

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

.module/RAM/ABS=0 mem_clr;       { Модуль памяти mem_clr с адреса 0  }

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

.var/dm/ram/circ buf_dm[0x3fdf]; { Циклический буфер в памяти данных }

jump BEGIN; nop; nop; nop; { Вектор прерывания сброса процессора }

rti; nop; nop; nop;        { Вектор прерывания IRQ2              }

rti; nop; nop; nop;        { Вектор прерывания IRQL1             }

rti; nop; nop; nop;        { Вектор прерывания IRQL0             }

rti; nop; nop; nop;        { Вектор прерывания SPORT0 TX         }

rti; nop; nop; nop;        { Вектор прерывания SPORT0 RX         }

rti; nop; nop; nop;        { Вектор прерывания IRQE              }

rti; nop; nop; nop;        { Вектор прерывания BDMA              }

rti; nop; nop; nop;        { Вектор прерывания SPORT1 TX (IRQ1)  }

rti; nop; nop; nop;        { Вектор прерывания SPORT1 RX (IRQ0)  }

rti; nop; nop; nop;        { Вектор прерывания TIMER             }

rti; nop; nop, nop;        { Вектор прерывания POWER DOWN        }

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

BEGIN:                                      { Метка начала программы }

 ax0 = b#0111111110000000; dm(pftype) = ax0; {Инициализация флагов PF}

{        │└┬┘││││76543210                                            }

{        │ │ ││││└+++++++ - PF0-PF7: 0-вход 1-выход                  }

{        │ │ │││└──────── - PM - выход -CMS                          }

{        │ │ ││└───────── - DM | 0-запрещен                          }

{        │ │ │└────────── - BM | 1-разрешен                          }

{        │ │ └─────────── - IOM--                                    }

{        │ └───────────── - От 0 до 7 циклов задержки BDMA           }

{        └ He используется, всегда=0                                 }

 ax0 = b#0000000010000000; dm(PFDATA) = ax0;{Управление светодиодом }

{                76543210                                           }

{                │   └──┴ - Вход:Код клавиш                         }

{                └─────── - Выход:Светодиод                         }

 i0 = ^buf_dm;       { Индексный регистр i0=адресу начала буфера     }

 l0 = %buf_dm;       { Регистр длины l0=длине буфера                 }

 m0 = 1;             { Регистр модификатора m0=1                     }

 ar = 0x1234;        { Записать данные в рабочий регистр ar          }

 cntr=10;            { Загрузить счетчик циклов                      }

 do CLR_DM until се; { Выполнять до CLR_DM пока счетчик не обнулится }

  dm(i0, m0) = ar;   { Заполнение очередной ячейки памяти данных     }

 CLR_DM:nop;         { Пустая команда                                }

 toggle fl2;         { Инвертировать вывод процессора FL2            }

 dm(0) = ar;         { Заполнение ячейки памяти данных с адресом 0   }

 ar = ar + 1;        {  увеличивающимися значениями                  }

 ax0 = dm(PFDATA);   { Читать код клавиш                             }

 dm(1) = ax0;        {  и записать в ячейку памяти данных по адресу 1}

 jump CLR_DM;        { Зациклить программу                           }

.endmod;             { Конец программы                               }

Имя данного файла можно изменить на любое другое, длиной от одного до восьми символов, разрешенных для имен файлов. Расширение «dsp» выбрано не случайно. При трансляции программы, компилятор будет искать файл программы именно с таким расширением. Если он не найдет такой файл, то выведет сообщение Preprocessor failed to open mem_clr.dsp.

Рассмотрим структуру и состав приведенного выше файла. Как видно из примера, в начале файла программы находится описание назначения программы, ее версии и пр. атрибуты, заключенные между символами /* и */ в качестве комментариев. Далее следуют три строки директив с комментариями, описывающими назначение этих директив и заключенными между фигурными скобками. Фигурные скобки также предназначены для вставки комментариев в программу. Файл def2181.h, включаемый в файл программы с помощью директивы #include, состоит из строк, присваивающих символьным именам регистров значение их адресов в области памяти данных процессора.

Использование символьных имен позволяет записывать в программе не конкретные цифровые значения адресов или данных, а их словесные описания, более понятные и легче запоминающиеся. Это делается для придания программе наглядности, предотвращения машинальных ошибок во время ее создания и облегчения ее понимания. Содержимое файла def2181.h приведено ниже.

.const IDMA=                0x3fe0;

.const BDMA_BIAD=           0x3fe1;

.const BDMA_BEAD=           0x3fe2;

.const BDMA_BDMA_Ctrl=      0x3fe3;

.const BDMA_BWCOUNT=        0x3fe4;

.const PFDATA=              0x3fe5;

.const PFTYPE=              0x3fе6;

.const SPORT1_Autobuf=      0x3fef;

.const SPORT1_RFSDIV=       0x3ff0;

.const SPORT1_SCLKDIV=      0x3ff1;

.const SPORT1_Control_Reg=  0x3ff2;

.const SPORT0_Autobuf=      0x3ff3;

.const SPORT0_RFSDIV=       0x3ff4;

.const SPORT0_SCLKDIV=      0x3ff5;

.const SPORT0_Control_Reg=  0x3ff6;

.const SPORT0_TX_Channels0= 0x3ff7;

.const SPORT0_TX_Channels1= 0x3ff8;

.const SPORT0_RX_Channels0= 0x3ff9;

.const SPORT0_RX_Channels1= 0x3ffa;

.const TSCALE=              0x3ffb;

.const TCOUNT=              0x3ffс;

.const TPERIOD=             0x3ffd;

.const DM_Wait_Reg=         0x3ffe;

.const System_Control_Reg=  0x3fff;

Описание этих символьных имен и их соответствие адресам памяти данных процессора приведено в табл. 6.1.

Таблица 6.1 Описание символьных имен регистров управления и состояния процессора ADSP-2181

Имя Описание Адрес
IDMA Регистр управления IDMA 0x3FE0
BDMA_BIAD Регистр внутреннего адреса BDMA 0x3FE1
BDMA_BEAD Регистр внешнего адреса BDMA 0x3FE2
BDMA_BDMA_Ctrl Регистр управления BDMA 0x3FE3
BDMA_BWCOUNT Регистр счетчика слов BDMA 0x3FE4
PFDATA Регистр данных программируемых флагов 0x3FE5
PFTYPE Регистр управления программируемыми флагами 0x3FE6
SPORT1_Autobuf Регистр управления автобуферизацией SPORT1 0x3FEF
SPORT1_RFSDIV Регистр делителя кадровых импульсов SPORT1 0x3FF0
SPORT1_SCLKDIV Регистр делителя тактовых импульсов SPORT1 0x3FF1
SPORT1_Control_Reg Регистр управления SPORT1 0x3FF2
SPORT0_Autobuf Регистр управления автобуферизацией SPORT0 0x3FF3
SPORT0_RFSDIV Регистр делителя кадровых импульсов SPORT0 0x3FF4
SPORT0_SCLKDIV Регистр делителя тактовых импульсов SPORT0 0x3FF5
SPORT0_Control_Reg Регистр управления SPORT0 0x3FF6
SPORT0_TX_Channels0 Регистр младшего слова передатчика SPORT0 0x3FF7
SPORT0_TX_Channels1 Регистр старшего слова передатчика SPORT0 0x3FF8
SPORT0_RX_Channels0 Регистр младшего слова приемника SPORT0 0x3FF9
SPORT0_RX_Channels1 Регистр старшего слова приемника SPORT0 0x3FFA
TSCALE Регистр масштабирования таймера 0x3FFB
TCOUNT Регистр счетчика таймера 0x3FFC
TPERIOD Регистр периода таймера 0x3FFD
DM_Wait_Reg Регистр тактов ожидания памяти данных 0x3FFE
System_Control_Reg Регистр управления системой 0x3FFF

Как видно из содержимого данного файла, в каждой его строке производится директивное назначение определенному символьному имени конкретного числового значения. Символьные имена могут быть произвольными, важно только, чтобы они одинаково записывались в данном файле и в самой программе. В дальнейшем мы часто будем использовать символьное описание регистров, для обращения к ним по записи или чтению из программы. В частности, в нашей программе mem_clr.dsp содержатся строки команд для обращения к регистру конфигурирования PFTYPE и регистру данных PFDATA программируемых флагов PF процессора. Файл def2181.h должен находиться в том же каталоге, в котором будет храниться файл программы во время ее трансляции. Иначе компилятор выдаст сообщение об ошибке во время компиляции программы.

Далее, в файле программы начинается запись команд. Поскольку с нулевого адреса памяти программ должны быть записаны векторы прерываний или их обработчики, первой располагается команда перехода jump BEGIN на начало программы, а затем команды возврата из прерывания rti для каждого из прерываний процессора. Все команды должны заканчиваться точкой с запятой, в соответствии с требованиями синтаксиса ассемблера. Заметьте, что в одной строке присутствует сразу несколько команд. Такая запись допускается компилятором ассемблера. Так как для каждого вектора прерывания в памяти программ отведено по четыре 24-разрядных ячейки памяти, а каждая команда процессора занимает одну 24-разрядную ячейку памяти, то оставшиеся неиспользованные ячейки памяти заполняются пустыми командами пор. Сразу же после метки BEGIN записаны команды инициализации конфигурационного регистра флагов PFTYPE с помощью рабочего регистра ax0 блока ALU процессора. Непосредственная запись константы в память данных не поддерживается процессором. Ниже располагаются строки комментариев с пояснением назначения каждого бита регистра флагов PFTYPE. Подобные записи позволяют хорошо документировать программу и облегчают тем самым ее отладку и последующее сопровождение. Аналогично описанным выше записям, в программе присутствуют строки команд записи в регистр данных PFDATA программируемых флагов слова управления светодиодом. Далее следуют команды инициализации некоторых регистров сигнального процессора. В частности, команда i0 = ^buf_dm; производит инициализацию индексного регистра, входящего в блок DAG сигнального процессора, т.е. присваивает индексному регистру i0 значение адреса начала буфера buf_dm, располагающегося в памяти данных процессора. Аналогично происходит инициализация других регистров этого блока и инициализация регистра ar блока ALU. Я намеренно указал на принадлежность регистров блокам процессора, для того чтобы показать связь между архитектурой процессора и выполняемой программой и тем самым облегчить понимание того, что происходит в самом процессоре при выполнении перечисленных команд программы. Далее в программе организуется циклическое заполнение памяти данных процессора значением регистра ar. После чего организуется цикл, состоящий из команд инвертирования выходного флага FL2 процессора и заполнения нулевой ячейки памяти регулярно увеличивающимся значением из регистра ar. Кроме того, в данном цикле организовано чтение состояния входов PF0-PF3 процессора и запись этих значений в ячейку памяти данных по адресу 1. Это сделано для того, чтобы при работе программы можно было увидеть с помощью осциллографа генерацию сигнала на выводе FL2, а также следить за изменением значений ячеек памяти с помощью симулятора или других аппаратно-программных средств, убеждаясь тем самым в правильной работе программы и нормальном функционировании процессора. Завершает программу директива окончания модуля программы endmod. В общем случае структура файла должна быть следующей:

/* Строки комментариев, описывающие */

/* название и назначение программы */

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

.Директива 1

.Директива 2

 ...

.Директива N

Метка1:  Команда1 и операторы; /*Комментарии*/

Метка2:  Команда2 и операторы; /*Комментарии*/

 ...

МеткаN:  КомандаN и операторы; /*Комментарии*/

.Директива окончания программы

Естественно, что комментарии, некоторые директивы, метки и команды с операторами могут отсутствовать в программе. Здесь приведен лишь общий пример записи программ.

Директивы и команды заранее определены языком программирования и не допускают произвольных записей. Метка может состоять из произвольного набора букв, символа подчеркивания и цифр без пробелов, начинающихся с буквы, длиной не более 32 символов, и должна заканчиваться двоеточием. Команды могут записываться в верхнем или нижнем регистре. Компилятор по умолчанию не распознает регистр записей программы, т.е. является контекстно-независимым, и допускает запись комментариев, директив, меток и команд с операторами в любом регистре. Это необходимо учитывать при задании имен меткам. Так, например, метка MET1: и met1: будут восприниматься компилятором как одна и та же, что приведет к сообщению об ошибке. Для того чтобы компилятор различал регистр букв, необходимо включить в строку его запуска ключ . Комментарии могут содержать любые наборы произвольных символов в одной или нескольких строчках, заключенных между открывающейся { и закрывающейся фигурной скобкой } или между символами /* и */.

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

Для трансляции программы с целью получения машинного загрузочного кода для процессора нам потребуются программные средства разработки. Семейство процессоров ADSP сопровождается полным набором программного обеспечения (трансляторы и эмуляторы) и аппаратных отладочных средств (отладочные комплекты и внутрисхемные эмуляторы), предоставляемые фирмой Analog Device для разработки программ и облегчения процесса освоения программирования на практике.

На сегодняшний день существует два программных пакета кросс средств для разработки и отладки программ для сигнального процессора ADSP-2181. С появлением новых процессоров продолжают добавляться дополнительные инструментарии разработки программ. Первый из этих пакетов входит в поставку отладочного комплекта EZ-KIT Lite и работает под управлением операционной системы DOS, или в режиме эмуляции DOS под Windows. Второй пакет Visual DSP, более позднего происхождения, распространяется самостоятельно и работает под управлением операционной системы Windows. Все кросс средства доступны на сайте компании Analog Device по адресу www.analog.com. Каким из этих пакетов пользоваться, обычно решает сам пользователь. Каждый из пакетов имеет свои преимущества и недостатки. Поэтому познакомим читателей с обоими пакетами поочередно, а они сами сделают свой выбор. Вначале рассмотрим пакет кросс средств для работы под DOS. Данные средства разработки для сигнальных процессоров ADSP-2181 включают в себя:

• System Builder (системный конфигуратор (построитель) программы). Это программный инструмент для описания особенностей оборудования. Он определяет структуру аппаратной системы, позволяя разработчику указать количество доступной памяти, местоположение программной памяти и памяти данных и любого отображенного в память порта ввода-вывода для аппаратного окружения. Данный построитель использует высокоуровневые конструкции, записываемые программистом в файле с расширением sys. После обработки данного файла построитель формирует файл архитектуры с расширением ach. Файл архитектуры используется в дальнейшем компоновщиком, симулятором и эмулятором. Допускается не выполнять процедуру системного конфигурирования при использовании готового файла архитектуры для конкретного процессора.

• C compiler (компилятор языка Си). Осуществляет проверку и преобразование текстов программы, написанных на языке Си формата ANSI, в тексты программ на языке ассемблер семейства ADSP-21XX. Кроме того, он поддерживает встроенный ассемблерный код. Данный компилятор необходим только для трансляции программ, написанных на языке Си. При создании программ на языке ассемблера компилятор Си не используется.

• Assembler (ассемблер-компилятор). Преобразует тексты программ, написанных на языке ассемблера, в объектный (машинный) код процессора. Он поддерживает высокоуровневый синтаксис набора команд и осуществляет полную проверку синтаксиса программы. Кроме того, компилятор поддерживает гибкую структуру макросов и включение дополнительных файлов с помощью директивы include с помощью программы препроцессора. Как правило, компилятор состоит из нескольких программных утилит.

• Linker (компоновщик). Объединяет отдельно ассемблированные модули программы (отдельные файлы с текстами программ) в единый связанный машинный код. При необходимости, на этапе компоновки программы используется программа библиотекаря, для создания законченных программных библиотек, включаемых впоследствии в основную программу.

• Simulators (симулятор). Позволяет отлаживать программы путем имитации работы сигнального процессора в памяти персонального компьютера. Интерактивный пользовательский интерфейс симулятора поддерживает полное символическое ассемблирование и дизассемблирование эмулируемых команд. Симулятор полностью эмулирует конфигурацию аппаратного обеспечения, описанную с помощью файла архитектуры. Он обеспечивает покомандное выполнение ассемблерного кода ADSP-2181 и позволяет отображать на экране монитора внутренние регистры и память процессора.

• Splitter («сплиттер» — распределитель). Эта программа-утилита по выходным данным компоновщика формирует файл для прошивки ПЗУ, из которой автоматически может производиться загрузка программы в память процессора через порт BDMA.

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

Полный пакет кросс средств можно приобрести вместе с отладочным комплектом EZ-Kit Lite у представителей фирмы Analog Device. Облегченную версию кросс средств, для сигнального процессора ADSP-2181 под управлением операционной системы DOS, можно скачать с сайта www.xxivek.narod.ru. В качестве отладочного средства при этом можно использовать тестовую плату, описанную в гл. 3.

Установка полного пакета на компьютер не вызывает сложностей. Его необходимо инсталлировать на диск С в корневой каталог ADI_DSP. Облегченная версия кросс средств с сайта www.xxivek.narod.ru просто распаковывается и копируется в каталог C:\ADI_DSP. После этого необходимо создать рабочий каталог для ваших будущих рабочих программ на любом диске. Для каждого нового проекта лучше всего создавать отдельный каталог или подкаталог, это позволит упорядочить все проекты.

После установки средств разработки, в каталоге ADI_DSP должны находиться подкаталоги с файлами транслятора, библиотеками и другими служебными файлами. Основные исполняемые файлы располагаются после инсталляции пакета в каталоге C:\ADI_DSP\21XX\BIN\. Перечень исполняемых файлов и их назначение приведены в табл. 6.2.

Таблица 6.2 Назначение исполняемых файлов

Имя файла Назначение
bld21.exe Системный конфигуратор (построитель) программы
cc1.exe, g21.exe Компиляторы языка Си
asm21.exe Компилятор ассемблера
asmpp.exe Ассемблер препроцессор
asm2.exe Ассемблер
ld21.exe Компоновщик (редактор связей)
Iib21.exe Библиотекарь (программа для работы с библиотеками программ)
spl21.exe Разделитель программ для программирования ПЗУ (сплиттер)
sim2181.exe Симулятор программ для процессора ADSP-2181
hexbin2.exe Преобразователь HEX кода в двоичный формат

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

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

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

@echo off

set path=c:\adi_dsp\21XX\bin

set adi_dsp=c:\adi_dsp

if %1 == goto no_file

echo Компиляция...

asm21 %1 -2181 -l

if not exist %1.obj goto error

echo ...завершена успешно pause

echo Компоновка...

ld21 %1 -a adsp2181 -e %1 -x -g

if not exist %1.lda goto next1

del %1.lda

:next1

ren %1.exe %1.lda

if not exist %1.lda goto error2

echo ...завершена успешно pause

echo Сплиттинг...

rem для загрузки через BDMA

spl21 %1.lda %1 -loader -2181 > %1.msg

echo ...завершен успешно

pause

echo Преобразование в бинарный файл...

hexbin2 %1.bnm %1.bin m 0 > %1.msg

echo ...завершено успешно

pause

goto end

:error

echo Ошибка компиляции!

pause

goto end

:error2

echo He найден файл %1.lda !

pause

goto end

:no_file

echo Используйте: asmdsp.bat имя файла без расширения

pause

:end

Введите текст этого файла с помощью любого текстового редактора с кодировкой DOS в компьютер и сохраните в файле с именем asmdsp.bat или скопируйте с компакт-диска, прилагаемого к книге. Он позволит автоматизировать процесс трансляции файлов с программами для сигнального процессора. Если просмотреть строки этого командного файла, то нетрудно понять что он делает. В первой строке командного файла находится команда запрета отображения командных строк на экран. Далее следуют две строки для установки пути к рабочему каталогу с файлами трансляции и переменной adi_dsp. Затем проверяется, было ли введено имя файла в командной строке при запуске данного файла. Если имени задано не было, производится переход на метку с названием no file, после которой на экран отобразится подсказка о правильном использовании командного файла. Команда pause выводит строку «Нажмите любую клавишу…» и ожидает соответствующее действие от пользователя. Если имя файла для трансляции было задано в строке при запуске командного файла, то переход на метку не производится и начинается процесс компиляции файла с программой. Все процессы трансляции предваряются соответствующим сообщением. Компиляция выполняется командой asm21 %1 -2181 -l. Здесь после вызова программы компилятора asm21.exe с именем файла из командной строки %1 используется ключ -2181 для задания типа процессора и ключ -I для генерации листинга программы. Список всех ключей для конфигуратора bld21.exe, компилятора asm21.exe, компоновщика ld21.exe, распределителя spl2.exe и симулятора sim2181.exe можно получить, запустив отдельно соответствующую программу без параметров или с ключом -help. Переведенный текст этих сообщений приведен в табл. 6.3.

Таблица 6.3 Формат записи программ и назначение ключей

bld21.exe [-ключ] имя_файла
-c Установить чувствительность к регистру символов
-help Вывести на экран справку о программе
asm21.exe [-ключ_1] [-ключ_2] … [-ключ_N] имя_файла
-Dvar[=exp] Определить идентификатор для Си препроцессора, например -dten=10
-c Установить чувствительность к регистру символов
-cp Включить Си препроцессор
-I Создать файл листинга программы
-i [глубина] Раскрыть содержимое включенных файлов в листинге с указанной глубиной
-m [глубина] Раскрыть макросы в файле листинга с указанной глубиной
-p Использовать только препроцессор
-s Отменить семантическую проверку много функциональных инструкций
-o имя_файла Переименовать выходной файл
-2181 Поддержать специальные ассемблерные инструкции для процессора ADSP-2181
-help Вывести на экран справку о программе
ld21.exe имя_файла1 [имя_файла2] … [имя_файлаN] [-ключ_1] [-ключ_2] … [-ключ_N]
-i имя_файла Указать командный списочный файл
-e имя Присвоить выходным файлам новое имя (по умолчанию 210x.exe)
-a имя_файла Указать файл описания архитектуры
-user имя_файла Поиск библиотечного файла, созданного утилитой построителя библиотеки Iib21.exe
-s размер Задать размер динамической памяти
-dir путь Указать пути каталога для поиска файлов библиотек
-lib Компоновать программу с библиотекой Си
-g Создать файл таблицы символов *.sym
-pmstack Переместить стек в память программ (PM)
-rom Использовать ПЗУ версии библиотечных программ Си
-c Создать стек для компилированных Си программ (DM)
-dryrun Быстрый запуск для теста на ошибки без создания файла загрузки
-x Создать файл распределения памяти *.map
-p Поместить копию библиотечной подпрограммы на загрузочных страницах
-group file Использовать файл групповых модулей
-help Вывести на экран справку о программе
spl21.exe входной_файл выходной_файл [-ключ_1] [-ключ_2] … [-ключ_N]
-dm Распределить только память данных DM
-pm Распределить только память программ РМ
-bm Распределить только память загрузки BM
-bs # Установить размер загрузочной памяти (2048, 1024, 512 или 256 байт)
-bb # Установить размер границы загрузки (2048 или 1024 байт)
-u Формат выходного файла Motorola S (по умолчанию)
-i Формат выходного файла Intel Hex
-us Формат Motorola S1, байтовый (только с ключами -pm или -dm)
-us2 Формат Motorola S2, байтовый (только с ключами -pm или -dm)
-ui Формат Intel Hex, байтовый (только с ключами -pm или -dm)
-loader Создать загрузочный файл
-bp # Большие загрузочные страницы, где # как HEX адрес
-bi # Большие загрузочные страницы, где # как HEX величина
-flag Большие загрузочные страницы с использованием выходных флагов
-Id Использовать специальный загрузчик
-2181 Создать код для процессора ADSP-2181
sim2181 [-a имя_файла] [-c] [-e имя_файла] [-h] [-k имя_файла] [-v] [-w имя_файла]
-a имя_файла Считывать при запуске файл архитектуры
-c Установить чувствительность к регистру символов
-e имя_файла Загрузить при запуске входной файл с расширением exe (lda)
-h Вывести на экран справку о программе
-k имя_файла Загрузить и выполнить файл командных строк
-o имя_файла Генерировать файл с сообщениями об ошибках
-v Избыточность
-w имя_файла Запустить симулятор с загрузкой ранее созданного файла конфигурации окон с расширением win

После компиляции программы будет создан файл с именем программы и расширением obj. Однако если на этапе компиляции будут обнаружены ошибки, этого не произойдет и с помощью команды if not exist %1.obj goto error будет осуществлен переход на метку error, для выдачи соответствующего сообщения. При успешной компиляции трансляция программы продолжится.

Компоновка программы выполняется с помощью командной строки: ld21 %1 -a adsp2181 -e %1 -x -g. Здесь после команды вызова компоновщика ld21.exe с именем файла из строки запуска командного файла %1, следует несколько ключей с параметрами. Ключ -a adsp2181 указывает имя файла архитектуры процессора adsp2181.ach. Данный файл создан с помощью построителя программ System Builder и входит в поставку пакета кросс средств. Он состоит из пяти следующих строк:

$2181

$ADSP2181

$0000 3FFF paxINT_PM_USER t

$0000 3FDF dadINT_DM_USER t

$

Этот файл содержит данные, определяющие тип процессора и структуру его памяти, и всегда должен находиться в том же каталоге, где находится файл транслируемой программы. Ключ -е %1 назначает имя выходного файла. Ключи -x и -g предназначены для генерации файла карты памяти *.map и файла с таблицей символьных имен *.sym соответственно. Эти файлы можно использовать в дальнейшем для анализа распределения памяти процессора. Файл с расширением sym необходим, кроме того, для отладки программы с помощью симулятора sim2181.exe. В результате компоновки будет получен файл с именем программы и расширением exe. Этот файл уже можно использовать для загрузки в симулятор или непосредственно в процессор, например через интерфейс IDMA. Формат данного файла приведен в табл. 6.4.

Таблица 6.4 Формат загрузочного файла

Символ Описание назначения
←←i Признак начала загрузочного файла
@PA Признак блока памяти программ РМ
0000 Адрес загрузки кодов в память РМ
Символ Описание назначения
123456 Первый код команды
789abc Второй код команды
def012 Третий код команды
и т.д.
#123XXXXXXXX Признак конца блока команд с контрольной суммой
@DA Признак блока памяти данных DM
0000 Адрес загрузки данных в память DM
1234 Первое слово данных
5679 Второе слово данных
и т.д.
#123XXXXXXXX Признак конца блока данных с контрольной суммой
←←o Признак конца загрузочного файла

X — контрольная сумма адреса и данных.

Позже мы подробно рассмотрим способ его загрузки в процессор через интерфейс IDMA. Несмотря на то, что этот файл имеет расширение exe, он не имеет ничего общего с исполняемыми файлами для персональных компьютеров. Тем не менее, случайный его запуск на компьютере может привести к непредсказуемым результатам. Непонятно, чем руководствовалась фирма Analog Device, давая такое расширение этому файлу при разработке кросс средств. Для устранения таких неприятных моментов в командный файл включены следующие четыре строчки:

if not exist %1.lda goto next1

del %1.lda

:next1

en %1.exe %1.lda

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

При успешной генерации загрузочного файла будет выведено соответствующее сообщение и осуществлен переход к группе команд для формирования файла прошивки для ПЗУ, из которого может производиться автоматическая загрузка процессора через интерфейс BDMA. Данный процесс называется «сплиттингом» (распределением) и осуществляется командой: spl21 %1.lda %1 - loader-2181 > %1.msg.

Здесь после команды вызова сплиттера sp21.exe с именем файла из командной строки с расширением Ida, следует несколько ключей и команда перенаправления вывода сообщений, с помощью символа >, в файл с расширением msg. Ключ -loader предназначен для добавления в выходной файл кода загрузчика, а ключ -2181 позволяет формировать код загрузки для процессора ADSP-2181. О коде загрузки я расскажу чуть позже.

В результате работы сплиттера будет создан файл прошивки для ПЗУ, с расширением bnm HEX формата Motorola. На практике, для программирования микросхем памяти чаще пользуются бинарным форматом файлов. Поэтому в командном файле добавлено еще несколько строк, осуществляющих преобразование файла bnm в бинарный файл с расширением bin. Для этого используется распространенная программа hexbin2.exe. Эту программу также можно найти на компакт-диске.

Теперь, когда мы познакомились со всеми процедурами трансляции, выполняемыми с помощью командного файла asmdsp.bat, можно начать транслировать нашу программу. Не забудьте, что вместе с программой в каталоге проекта должен находиться файл описания def2181.h, файл архитектуры adsp2181.ach и созданный и описанный выше командный файл asmdsp.bat.

Выполните трансляцию программы mem_clr.dsp с помощью командной строки asmdsp.bat mem_clr. Обратите внимание на то, что в качестве параметра для командного файла используется имя нашей программы без расширения. Оно будет автоматически подставляться вместо символов %1 командного файла. В результате работы командного файла на экране должны последовательно появиться сообщения:

Компиляция...

...завершена успешно

Нажмите любую клавишу...

Компоновка...

...завершена успешно

Нажмите любую клавишу...

Сплиттинг...

...завершен успешно

Нажмите любую клавишу...

Преобразование в бинарный файл...

...завершено успешно

Нажмите любую клавишу...

По завершении работы командного файла в каталоге с программой должны появиться файлы с именем программы и расширениями int, lst, obj, lda, map, sym, msg, cde, bnl, bnm, bnu и bin. Описание назначения данных файлов проекта в краткой форме приведено в табл. 6.5.

Таблица 6.5 Описание расширений файлов проекта

Расширение Описание
bat Командный файл
sys Исходный файл системной архитектуры
ach Файл описания архитектуры
dsp Файл ассемблерного модуля (текст программы)
lst Файл листинга
int Файл инициализации
obj Объектный файл
cde Файл кода
dat Файл инициализации данных кода
exe (lda) Файл загрузки образа памяти
map Файл распределения памяти
sym Файл символов
bnu Выходной файл разделителя программ. Содержит старшие байты
bnm Выходной файл разделителя программ. Содержит средние байты
bnl Выходной файл разделителя программ. Содержит младшие байты
bin Файл для программирования ПЗУ в двоичном формате
msg Файл сообщений

Итак, с помощью приведенного выше командного файла мы получили необходимые нам файлы с расширениями lda и bin для непосредственной загрузки в память процессора и для прошивки ПЗУ соответственно. Файл с расширением sym понадобится нам для отладки программы с помощью программы симулятора sim2181.exe.

Остальные перечисленные выше файлы в каталоге с программой являются вспомогательными, которые после их просмотра и изучения можно смело удалить для очистки каталога. Например, файл с расширением lst содержит листинг программы с нумерацией всех строк программы и машинными кодами процессора, соответствующими ассемблерным командам программы. С его помощью можно увидеть соответствие ассемблерных команд машинным кодам сигнального процессора.

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

del *.map

del *.lst

del *.hex

del *.msg

del *.cde

del *.int

del *.obj

del *.bnl

del *.bnm

del *.bnu

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

Теперь можно приступить к отладке программы. Проследить за ходом выполнения программы и изменением состояния внутренних регистров и ячеек памяти процессора нам поможет программа симулятора sim2181.exe, входящая в состав средств разработки программ.

Данная программа работает только в операционной системе DOS и даже не допускает работу в режиме эмуляции DOS из Windows. Поэтому для запуска данного симулятора необходимо перегрузить компьютер в режим работы DOS, после чего необходимо запустить программу симулятора в командной строке sim2181.exe. После загрузки программы на экране монитора должно появиться окно с изображением названия и версии программы (рис. 6.1).

Рис. 6.1. Окно с изображением названия и версии программы

Несколько секунд спустя должно появиться окно с главным меню и приглашением к вводу команд в центре экрана (рис. 6.2).

Рис. 6.2. Окно с главным меню

Главное меню программы состоит из десяти раскрывающихся закладок команд. Симулятор имеет встроенную справочную систему по всем командам меню, вызываемую с помощью клавиши F1 клавиатуры. Назначение клавиш управления симулятора приведено в табл. 6.6.

Таблица 6.6. Назначение клавиш управления симулятора

Клавиша или комбинация Описание выполняемой функции
Функции выполнения программы
F4 Запустить программу на выполнение
F10 Выполнять программу по шагам
Shift+F10 Выполнять N шагов программы
F9 Установить/сбросить точку останова программы
Shift+F9 Установить/сбросить специальную точку останова программы
Функции памяти
Ctrl+D Дамп памяти
Ctrl+F Заполнить память
Ctrl+G Перейти по адресу памяти
Ctrl+M Загрузить память
Функции размера окна
Shift+F5 Увеличить окно по вертикали
Shift+F6 Уменьшить окно по вертикали
Shift+F7 Увеличить окно по горизонтали
Shift+F8 Уменьшить окно по горизонтали
Функции перемещения окна
F5 Переместить окно вверх
F6 Переместить окно вниз
F7 Переместить окно влево
F8 Переместить окно вправо
Функции выбора окна
ESC Закрыть текущее окно
F2 Выбрать следующее окно
F3 Выбрать окно главного меню
Ctrl+L Показать список активных окон
Функции отображения окна
F1 Вызов окна помощи
Ctrl+T Переключение формата отображения окна

Для перехода в главное меню и загрузки программы нажмите последовательно клавиши Esc и F3 на клавиатуре. С помощью стрелок курсора выделите закладку File главного меню и раскройте ее, нажав клавишу Enter. В раскрывшемся списке команд выберите команду Load Executable File (загрузить исполняемый файл), а в открывшемся окне ввода введите имя файла mem_clr.lda и завершите ввод, нажав клавишу Enter.

Откройте в пунктах главного меню Memory и Register окна памяти программ Program Memory, памяти данных Data Memory, флагов Flags, регистров генератора адреса DAG Registers и регистров арифметико-логического устройства Computational Alternate Registers. После чего разместите эти окна на экране с помощью клавиш управления окнами симулятора в соответствии с рис. 6.3, используя клавиши управления, описанные в табл. 6.6.

Рис. 6.3. Экран управления окнами симулятора

Данные окна позволят наблюдать за ходом выполнения программы и состоянием памяти и регистров процессора. Теперь можно выполнять программу по шагам, нажимая клавишу F10 на клавиатуре, или запустить автоматическое выполнение программы с помощью клавиши F4.

Останов программы производится повторным нажатием клавиши F4. Во время выполнения программы в окне памяти программ Program Memory можно наблюдать процесс выполнения ассемблерных команд, а в окнах регистров и памяти данных изменение значений регистров и ячеек памяти.

Для сохранения конфигурации окон и использования этой конфигурации при повторных запусках симулятора можно сохранить ее в файле с помощью команды Save Window File из закладки File главного меню. При сохранении конфигурации необходимо будет задать имя файла, например mem_clr. После сохранения конфигурации и выхода из симулятора в каталоге будет находиться файл с именем mem_clr.win. Для выхода из симулятора необходимо выбрать команду Exit или Quit из закладки Quit главного меню и в открывшемся окне подтверждения выхода нажать поочередно клавишу пробела Space, а затем клавишу Enter. При новом запуске симулятора, вместо повторного открытия окон, достаточно будет загрузить файл с помощью команды Load Window File из закладки File главного меню симулятора.

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

Глава 7. Порт BDMA

В этой главе описывается порт байтового прямого доступа к памяти процессора, под названием BDMA (Byte Data Memory Access).

Теперь можно приступить к загрузке транслированной и отлаженной программы непосредственно в сигнальный процессор. Для выполнения данной процедуры и практического освоения сигнального процессора с отладкой программ аппаратно можно воспользоваться тестовой платой, описанной в гл. 3.

Запрограммируйте флэш ПЗУ типа Am29F040 содержимым файла mem_clr.bin с помощью любого подходящего для этих целей программатора и вставьте запрограммированную микросхему в панельку на место микросхемы D7 тестовой платы. После подачи напряжения питания на тестовую плату произойдет автоматическая загрузка программы из ПЗУ через порт BDMA в память сигнального процессора, и ее выполнение. Убедиться в том, что программа работает, можно будет с помощью осциллографа, подключенного к выводу FL2 процессора. На этом выводе должен формироваться сигнал в виде меандра с частотой около 2МГц, а светодиод HL2 должен при этом светиться.

Рассмотрим подробнее механизм автоматической загрузки сигнального процессора из ПЗУ, для лучшего понимания происходящих при этом процессов. При подаче питания на тестовую плату, описанную в гл. 3, цепь сброса R1, CP1 формирует сигнал -RKEY, который устанавливает триггер, построенный на элементах D6.1 и D6.2, в состояние, при котором сигнал BMODE будет находиться в состоянии логического нуля. Сигнальный процессор анализирует состояние данного сигнала и сигнала на входе вывода MMAP после сброса и распознает, что загрузка программы в программную память процессора будет производиться из ПЗУ через интерфейс BDMA. При этом процессор автоматически заносит в регистры порта BDMA определенные значения, описанные в предыдущей главе, для того чтобы произвелась автоматическая загрузка 32 слов программы-загрузчика разрядностью 24 бита побайтно в программную память процессора и затем ей было передано управление для загрузки остальной части программы.

Как было сказано выше, программа-загрузчик автоматически записывается в начало файла прошивки ПЗУ с помощью сплиттера во время трансляции программы. После автоматической загрузки из ПЗУ в память программ процессора 32 слов программы- загрузчика через интерфейс BDMA происходит перезапуск процессора и начинает выполняться программа загрузчика, которая осуществляет полную загрузку основной рабочей программы из ПЗУ в процессор.

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

В файле mem_clr.bin и в ПЗУ все коды 24-разрядных слов команд процессора располагаются в строгом порядке. Первым располагается в ПЗУ старший байт команды, затем следует средний байт и последним записывается младший байт команды. Формат хранения слов программы в ПЗУ приведен в табл. 7.1.

Таблица 7.1 Формат хранения слов программы в ПЗУ

Адрес памяти программ Слово программы Адрес памяти ПЗУ Байты программы
0x0000 0xABCDEF 0x00 0xAB
0x01 0xCD
0x02 0xEF
0x0001 0x123456 0x03 0x12
0x04 0x34
0x05 0x56
и т.д.

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

Глава 8. Порт IDMA

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

Помимо порта прямого доступа к байтовой памяти BDMA (Byte Data Memory Access), сигнальный процессор ADSP-2181 имеет порт прямого доступа к внутренней памяти процессора IDMA (Internal Data Memory Access). Он представляет собой 16-разрядный параллельный порт, через который можно читать и записывать данные памяти процессора. Порт IDMA имеет 16-разрядную мультиплексированную шину адреса/данных IAD0–IAD15, 4 сигнала управления и 1 сигнал контроля. К сигналам управления относятся: сигнал выбора порта -IS, сигнал записи адреса ячейки памяти IAL, сигнал чтения -IRD и записи -IWR данных через порт. Сигнал контроля -IACK позволяет определить готовность порта IDMA. При чтении и записи памяти через IDMA данные транслируются через буферный регистр порта IDMA. В памяти данных процессора по адресу 0x3FE0 находится регистр управления IDMA, который предназначен для хранения адреса ячейки памяти, к которой будет производиться обращение через порт IDMA. Формат этого регистра представлен в табл. 8.1.

Таблица 8.1 Формат данных регистра управления IDMA

Разряд Назначение
15 Не используется
14 Указатель типа памяти: 0=память программ (РМ) 1=память данных (DM)
13–0 Значение начального адреса памяти процессора при обмене через IDMA (от 0 до 0x3FFF)

Порт IDMA имеет встроенную функцию автоинкремента (автоматического увеличения на единицу адреса памяти), что позволяет ускорить выполнение блочных операций. Кроме того, порт IDMA позволяет выполнять загрузку памяти программ процессора с автоматическим запуском программы после заполнения нулевой ячейки памяти. Протокол обращения к памяти процессора через порт IDMA достаточно прост и показан на рис. 8.1.

Рис. 8.1. Алгоритм обращения к памяти процессора

Вначале все сигналы управления портом переводятся в пассивное состояние и проверятся готовность IDMA, путем ожидания установки сигнала -IACK в логический ноль. Затем осуществляется вывод на шину IAD0–15 сигналов адреса памяти процессора, к которой будет производиться обращение. После чего формируется строб сигнала записи адреса IAL в регистр управления порта IDMA. Временная диаграмма данной операции показана на рис. 8.2, а в табл. 8.2 приведены временные параметры для этой диаграммы.

Рис. 8.2. Временная диаграмма операции защелкивания адреса IDMA

Таблица 8.2 Временные параметры диаграммы защелкивания адреса IDMA

Параметр Минимум
Защелкивание адреса IDMA
Требуемые длительности:
tIALP длительность защелкивания адреса, нс1,2 10
tIASU установка адреса перед окончанием защелкивания, нс2 5
tIAH удержание адреса после защелкивания, нс2 2
tIKA-IACK=0 перед защелкиванием, нс1 0
tIALS начало записи или чтения после защелкивания, нс2,3 3

Примечания:

1 Начало защелкивания — IS=0 и IAL=1.

2 Конец защелкивания — IS=1 или IAL=0.

3 Начало записи или чтения — IS=0 и (IWR=0 или IRD=0).

Как видно из таблицы, минимальные временные значения сигналов не превышают 10 нс, что говорит о поддержке высокой скорости операций портом IDMA. Далее производится операция чтения или записи памяти. При операции чтения данные считываются с шины IAD0–IAD15 во время активизации управляющего сигнала -IRD.

При операции записи данные выставляются на шину IAD0–IAD15, и записываются в память процессора с помощью активизации сигнала -IWR.

Порт IDMA поддерживает короткий (быстрый) и длинный (долгий) циклы обращения к памяти. Во время короткого цикла данные читаются и записываются без ожидания готовности порта по сигналу -IACK, используя при этом буфер порта IDMA с данными. Временные диаграммы для данных циклов обращения показаны на рис. 8.3 и 8.4 соответственно. В табл. 8.3 и 8.4 приведены характеристики сигналов для этих диаграмм.

Рис. 8.3. Временные диаграммы короткого цикла чтения через порт IDMA

Рис. 8.4. Временные диаграммы короткого цикла записи через порт IDMA

Таблица 8.3 Временные параметры диаграммы короткого цикла чтения через порт IDMA

Параметр Минимум Максимум
Короткий цикл чтения через IDMA
Требуемые длительности:
tIKR-IACK=0 до начала чтения1, нс 0
tIRP Продолжительность сигнала чтения, нс 15
Характеристики переключения:
tIKHR-IACK=0 после начала чтения1, нс 15
tIKDH Удержание данных после окончания чтения2, нс 0
tIKDD Сброс данных после окончания чтения2, нс 10
tIRDE Активизация предыдущих данных, нс 0
tIRDV Достоверность предыдущих данных 15

Примечания:

1 Начало чтения: -IS=0 и -IRD=0.

2 Конец чтения: -IS=1 или -IRD=1.

Таблица 8.4 Временные параметры диаграммы короткого цикла записи через порт IDMA

Параметр Минимум Максимум
Короткий цикл записи через IDMA
Требуемые длительности:
tIKW-IACK=0 до начала записи1, нс 0
tIWP Продолжительность записи1,2, нс 15
tIDSU Установка данных до окончания записи2, нс 5
tIDH Удержание данных после окончания записи2, нс 2
Характеристики переключения:
tIKHW от начала записи до -IACK=1, нс 15

Примечания:

1 Начало записи: -IS=0 и -IWR=0.

2 Конец записи: -IS=1 или -IWR=1.

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

Временные диаграммы для данных циклов обращения показаны на рис. 8.5 и 8.6 соответственно. В табл. 8.5 и 8.6 приведены характеристики сигналов для этих диаграмм.

Рис. 8.5. Временные диаграммы длинного цикла чтения через порт IDMA

Рис. 8.6. Временные диаграммы длинного цикла записи через порт IDMA

Таблица 8.5 Временные параметры диаграммы длинного цикла чтения через порт IDMA

Параметр Минимум Максимум
Длинный цикл чтения через IDMA
Требуемые длительности:
tIKR-IACK=0 до начала чтения1, нс 0
tIRP Продолжительность сигнала чтения, нс 15
Характеристики переключения:
tIKHR-IACK=0 после начала чтения1, нс 15
tIKDS Установка данных перед -IACK=0, нс 0,5 tCK5-10
tIKDH Удержание данных после окончания чтения2, нс 0
tIKDD Сброс данных после окончания чтения2, нс 10
tIRDE Активизация предыдущих данных, нс 0
tIRDV Достоверность предыдущих данных, нс 15
tIRDH1 Удержание предыдущих данных (DM/PM1), нс 2 tCK-5
tIRDH2 Удержание предыдущих данных (PM2), нс tCK-5

Примечания:

1 Начало чтения: -IS=0 и -IRD=0.

2 Конец чтения:-IS=1 или -IRD=1.

3 Чтение памяти DM или первой половины РМ.

4 Чтение второй половины РМ.

5 tCK — период тактовой частоты процессора.

Таблица 8.6 Временные параметры диаграммы длинного цикла записи через порт IDMA

Параметр Минимум Максимум
Длинный цикл записи через IDMA
Требуемые длительности:
tIKW-IACK=0 до начала записи1, нс 0
tIKSU Установка данных перед -IACK=0, нс 0,5 tCK2+1
tIKH Удержание данных после -IACK=0, нс 2
Характеристики переключения:
tIKLW От начала записи до -IACK=0, нс 1,5 tCK
tIKHW От начала записи до -IACK=1, нс 15

Примечания:

1 Начало записи: -IS=0 и -IWR=0.

2 tСK — период тактовой частоты процессора.

Сигнал подтверждения данных -IACK допускается не использовать, если скорость обращения к порту со стороны адаптера невысокая и достоверность данных обеспечивается задержкой самих сигналов управления.

При обращении через порт IDMA к памяти данных операции чтения и записи выполняются за один цикл, поскольку разрядность порта составляет 16 бит. Однако при обращении к 24-разрядным данным памяти программ требуется два цикла обращения. В первом цикле происходит чтение или запись старших 16 бит слова памяти программ. Во втором цикле по линиям IAD0–IAD7 передаются младшие 8 бит слова. Линии IAD8–IAD15 при этом игнорируются. Автоинкремента адреса между этими циклами не происходит.

Через порт IDMA возможен доступ ко всей памяти процессора, за исключением регистров управления и состояния, отображенных на область памяти данных. При обращении через IDMA к области памяти данных, отведенной для регистров управления и состояния с адреса 0x3FE0 по адрес 0x3FFF, запись и чтение данных все же будет производиться. Но эта область памяти фактически будет дополнительной для пользователя, поскольку она дублирует системную область памяти данных, отведенную для регистров управления и состояния процессора.

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

Процессор ADSP-2181 поддерживает также начальную загрузку программ в память программ через порт IDMA. Для этого необходимо установить сигналы на выводах процессора BMODE=1 и MMAP=0. Затем необходимо произвести сброс процессора и загрузить программу в память программ процессора, начиная с адреса 1 через порт IDMA. Кроме того, можно записать произвольные данные в память данных процессора. После этого следует записать слово программы по адресу 0, и процессор запустит загруженную программу.

Глава 9. Адаптер LPT-IDMA

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

Для этих целей был разработан небольшой адаптер LPT-IDMA, который позволяет подключить порт IDMA сигнального процессора к LPT порту персонального компьютера. Схема этого адаптера приведена на рис. 9.1.

Рис. 9.1. Схема адаптера (начало)

Рис. 9.1. Схема адаптера (продолжение)

Рис. 9.1. Схема адаптера (окончание)

Адаптер выполнен на базе одной программируемой логической микросхемы D1 типа XC9536-15VQ44C фирмы XILINX. Схема внутреннего содержимого этой микросхемы представлена на рис. 9.2.

Рис. 9.2. Функциональная схема микросхемы (начало)

Рис. 9.2. Функциональная схема микросхемы (окончание)

Данная схема обеспечивает формирование 16-разрядной шины адреса и управляющих сигналов для порта IDMA с помощью 8-разрядной шины данных LPT порта. Чтение 16-разрядных данных из порта IDMA осуществляется через сигналы состояния LPT порта с использованием мультиплексоров M2_1, запрограммированных в схеме ПЛИС.

Прошивка для программирования данной ПЛИС в виде файла lpt_idma.jed находится на диске, прилагаемом к книге. Программирование ПЛИС осуществляется через соединитель J1 с помощью программатора, описываемого в приложении.

Все элементы адаптера можно распаять на небольшой макетной плате или изготовить для этих целей специальную печатную плату. Адаптер подключается к LPT порту компьютера с помощью ленточного 25-жильного кабеля, через разъем X1 «LPT». Чертеж такого кабеля изображен на рис. 9.3, а в табл. 9.1 приведено назначение цепей и соответствие контактов разъемов.

Рис. 9.3. Ленточный 25-жильный кабель

Таблица 9.1 Назначение цепей кабеля LPT

Цепь Вилка DB-25M Розетка DB-25F Цепь Вилка DB-25M Розетка DB-25F
-STB 1 1 -AUTOLF 14 14
D0 2 2 -ERR 15 15
D1 3 3 -INIT 16 16
D2 4 4 -SELIN 17 17
D3 5 5 GND 18 18
D4 6 6 GND 19 19
D5 7 7 GND 20 20
D6 8 8 GND 21 21
D7 9 9 GND 22 22
-ACK 10 10 GND 23 23
BUSY 11 11 GND 24 24
РЕ 12 12 GND 25 25
SEL 13 13 - - -

С помощью разъемов XU и XP адаптер подключается непосредственно к устройству с сигнальным процессором через интерфейсный порт IDMA.

Питание адаптера осуществляется от источника питания напряжением +5 В самого устройства. В качестве такого устройства с сигнальным процессором можно использовать тестовую плату, описанную ранее. Эта плата имеет все необходимое для подключения адаптера LPT-IDMA без всяких переделок.

Все схемы и проект прошивки для ПЛИС прилагаются в виде соответствующих файлов на компакт-диске этой книги.

Глава 10. Менеджер памяти

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

Для того чтобы можно было использовать адаптер LPT-IDMA для загрузки программ и данных в сигнальный процессор, а также иметь возможность редактировать содержимое памяти сигнального процессора во время его работы, мною была написана программа менеджера памяти цифрового сигнального процессора «mngdsp». Эта программа является приложением DOS и может работать в режиме DOS под Windows95/98/Me. Данная программа в составе проекта для Borland С++ 3.1, с исходными текстами программы находится на диске, прилагаемом к книге.

После запуска программы mngdsp.exe на экране монитора должно появиться окно, изображенное на рис. 10.1.

Рис. 10.1. Экран монитора после запуска программы mngdsp.exe

Данное окно отображает содержимое памяти сигнального процессора в шестнадцатеричном формате. Внизу этого окна приведены команды управления программой. При перемещении маркера по окну с помощью клавиш управления, можно выбрать любую доступную ячейку памяти процессора, для записи в нее произвольных данных. Адрес выбранной ячейки памяти отображается слева вверху. Переключение между памятью данных и памятью программ процессора производится с помощью клавиши TAB клавиатуры. Адаптер позволяет подключаться параллельно к двум портам IDMA разных процессоров. Например, к мультипроцессорному устройству. Для этого он использует сигнал -SEL, подключаемый к выводу - IS порта IDMA. Поскольку при пассивном состоянии данного сигнала порт IDMA не активизируется, допускается запараллеливание всех сигналов IDMA двух процессоров, за исключением сигнала -IS, который позволит выбирать один из двух процессоров. При такой схеме включения необходимо к выводу -IS одного из двух процессоров подключать сигнал -SEL непосредственно, а к выводу -IS второго процессора через инвертор. Выбор процессора из программы производится клавишами F1 и F2. С помощью клавиши F3 можно заполнить всю память данных процессора произвольным числовым значением. Клавиша F4 позволяет очистить память данных процессора путем записи во всю область памяти нулевого значения. Клавиша F8 производит принудительный сброс процессора путем формирования сигнала сброса -INIT для процессора. Кроме того, программа менеджер позволяет загрузить программу в память процессора и запустить ее. Для этого используется клавиша F9. После нажатия этой клавиши, программа запросит имя загружаемого файла, а также предложит загрузить файл с именем dsp.lda, используемым в программе по умолчанию. Поэтому перед запуском программы можно переименовать файл, который должен загружаться в процессор, в файл с именем dsp.lda либо ввести имя загружаемого файла по запросу программы. О формате данного файла и о том, как получить такой файл, было рассказано ранее.

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

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

Рис. 10.2. Структурная схема подключения двух процессоров

Как видно из схемы, ведущий процессор подключен к порту IDMA ведомого процессора с использованием сигнала обращения к портам ввода-вывода -IOMS, сигнала записи -IWR, двух сигналов программируемых флагов PF0 и PF2, адресного сигнала A0, шины данных D8–D23 и сигнала синхронизации тактовой частоты CLKOUT. Такая схема включения позволяет выполнять операцию записи данных через порт IDMA ведомого процессора с помощью одной команды записи данных в порт ввода-вывода io(address)=data. Сигнал CLKOUT обеспечивает маскирование адресной линии A0 при формировании сигнала защелки адреса IAL. Такое маскирование необходимо для блокировки переходных процессов на линии А0 при установке адреса. Это хорошо видно из временной диаграммы цикла записи данных процессором в порт ввода-вывода, приведенной на рис. 10.3.

Рис. 10.3. Временная диаграмма цикла записи

Сигнальные цепи PF2 и PF0 используются ведущим процессором для активизации схемы защелки адреса в порт IDMA и для анализа состояния готовности порта IDMA ведомого процессора.

Ниже приведен исходный текст программы idmaidma.dsp для ведущего процессора данной схемы, позволяющей ему загрузить в память программ ведомого процессора массив данных, размещенных в файле idmaidma.dat, являющихся программой для ведомого процессора.

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

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

/* Эта программа транслирует данные от ведущего процессора 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;

Директива ENDSYS

Директива ENDSYS должна быть последней командой в файле. Системный конфигуратор останавливает свою работу на директиве .ENDSYS. Директива имеет форму записи:

.ENDSYS;

Ниже приведен пример законченного файла example.sys для системного конфигуратора.

.SYSTEM example;

.ADSP2181;

.MMAP0;

.SEG/PM/RAM/ABS=0x0000/CODE/DATA mem_pm[0x4000];

.SEG/DM/RAM/ABS=0x0000/DATA mem_dm[0x3FE0];

.ENDSYS;

После обработки этого файла системным конфигуратором должен получиться файл example.ach с таким содержимым:

$EXAMPLE

$ADSP2181

$MMAP0

$0000 3FFF pax_PM t

$0000 3FDF dadMEM_DM t

$

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

Директива MODULE

Директива MODULE обозначает начало программного модуля и определяет название модуля. Как было сказано ранее, программа для ADSP-2181 может состоять из одного или нескольких модулей, которые отдельно ассемблируются и затем связываются вместе. Каждый файл с исходным текстом программы может содержать только один программный модуль. Директива имеет следующую форму записи:

.МОDULЕ/ПАРАМЕТР1/ПАРАМЕТР2 ... ИМЯ_МОДУЛЯ;

Параметры могут быть следующими:

RAM или ROM — тип памяти для размещения программы;

ABS=адрес — абсолютный стартовый адрес (не используется вместе с директивой STATIC);

SEG=сегмент — размещение программы в указанном сегменте;

STATIC — статичное размещение модуля в памяти (не используется вместе с директивой ABS).

Параметр RAM (ОЗУ) или ROM (ПЗУ) определяет тип памяти процессора для размещения программы. Если тип памяти не определен, то по умолчанию принимается тип RAM.

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

Параметр SEG размещает модуль в указанный сегмент памяти, который объявлен в файле системной конфигурации. Если определить оба параметра ABS и SEG и указать абсолютные адреса, которых нет в данном сегменте, компоновщик выдаст сообщение об ошибке.

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

.MODULE/RAM/ABS=0 demo;

{Определение имени demo программного модуля}

{с размещением в ОЗУ по абсолютному адресу 0}

Директива CONST

Директива CONST определяет соответствие между именем константы и ее значением. Данная директива имеет следующую форму записи:

.CONST имя_константы1 = значение1, имя_константы2 = значение2...;

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

+ — сложение;

- — вычитание;

* — умножение;

/ — деление;

% — модуль (целая часть от деления);

( — левая скобка;

) — правая скобка;

& — логическое «И» (AND);

| — логическое «ИЛИ» (OR);

~ — исключающее «ИЛИ» (XOR);

<< — логический сдвиг влево;

>> — логический сдвиг вправо.

Запись чисел в программах может осуществляться в нескольких форматах. Для записи шестнадцатеричных чисел используется префикс 0x (ноль и икс) или H#. Например:

0x24FF, H#CF8A

Для восьмеричных чисел применяется префикс 0 (ноль):

0777, 0123, 07777

Двоичные числа записываются с префиксом B#:

В#01110100

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

1024, -55, 0

Пример записи арифметического выражения:

X = (29+129)-(128-48)/3

Пример логического выражения:

Y = 0x55&0x0F

Пример записи директивы:

.CONST N=1024, LEN_BUF=N/2; {Число точек отсчета = 1024, длина буфера = 512}

Директива VAR

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

Директива VAR имеет следующую форму записи:

.VAR/параметр1/параметр2 ... имя_буфера[длина],...;

С директивой могут использоваться следующие параметры:

PM или DM — тип памяти для размещения буфера;

RAM или ROM — тип памяти процессора;

ABS=адрес — абсолютный адрес (нельзя использовать вместе с директивой STATIC);

SEG=сегмент — размещение буфера в сегменте, объявленном системным конфигуратором;

CIRC — кольцевой буфер;

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

Одна директива VAR позволяет объявить в одной строке длиной до 200 символов несколько буферов, разделенных запятыми.

Буферы могут быть линейными и кольцевыми. Буферы могут быть произвольной длины от единицы до размера, не превышающего объем памяти процессора. Линейный буфер размещается в памяти с любого адреса. Кольцевой буфер может быть размещен в памяти с некоторыми ограничениями, связанными с аппаратными особенностями памяти процессоров. Так, кольцевой буфер должен стартовать с базового адреса, который кратен 2 в степени n, где n — количество бит требуемых для представления длины буфера в двоичном виде. Это необходимо учитывать при создании кольцевых буферов с параметром ABS.

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

Буферы могут быть размещены как в памяти программ PM, так и в памяти данных DM, по умолчанию. Тип памяти по умолчанию устанавливается в RAM для памяти DM и PM.

Параметр ABS размещает буфер с указанного стартового адреса, делая его неперемещаемым.

Параметр SEG размещает буфер в указанном сегменте памяти, который был объявлен в файле системного конфигуратора.

Параметр CIRC определяет кольцевой буфер. Буфер будет организован как линейный, если не применен атрибут CIRC.

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

Пример объявления буфера:

.VAR/PM/RAM/SEG=segdata buffer[10];

Здесь линейный буфер объявлен в памяти программ RAM, который перемещаем в пределах сегмента с именем segdata. Буфер с именем buffer состоит из 10 ячеек в памяти программ. Длина буфера указывается в квадратных скобках.

Для объявления одномерных буферов, т.е. простых переменных, применяется директива VAR без указания длины буфера. Например:

.VAR/DM/RAM/ABS=0x000C xdata;

Данная директива объявляет однословную переменную с именем xdata в памяти данных RAM по шестнадцатеричному адресу 0x000C.

Ниже приведен пример объявления автоматически перемещаемого кольцевого буфера с именем buffer_c, длина которого определяется величиной константы size, объявленной директивой CONST.

.CONST size = 15;

.VAR/DM/CIRC buffer_c[size];

Ниже приведены примеры, позволяющие понять, как можно размещать циклические буферы в памяти. Следующий оператор объявляет кольцевой буфер с именем abuf из шести ячеек памяти:

.VAR/CIRC abuf[6];

Поскольку ближайшим числом больше шести и кратным двум является число 8, то базовый (стартовый) адрес буфера должен быть кратен 8. Три младших значимых разряда (МЗР) этого адреса будут равны нулю. В табл. 11.1 показано размещение этого буфера в памяти.

Таблица 11.1 Размещение одного циклического буфера в памяти сигнального процессора

Имя буфера Элемент буфера Двоичный адрес
abuf abuf[0] XXXXXXXXXX0000
abuf[1] XXXXXXXXXX0001
abuf[2] XXXXXXXXXX0010
abuf[3] XXXXXXXXXX0011
abuf[4] XXXXXXXXXX0100
abuf[5] XXXXXXXXXX0101
XXXXXXXXXX0110

Если в одной строке объявлены несколько буферов с параметром CIRC, то будет создан один кольцевой буфер, вмещающий в себя все буферы. Первый из этих буферов будет кольцевым, а отдельные буферы будут простыми линейными буферами. Например, следующая директива создает один кольцевой буфер abuf и два линейных буфера с именами bbuf и cbuf.

.VAR/CIRC abuf[6], bbuf[3], cbuf[5];

Для размещения всех этих буферов в памяти процессора потребуется 6+3+5=14 ячеек памяти. Поскольку первым в директиве объявлен буфер abuf, то он будет кольцевым. Ближайшим числом больше 14 и кратным двум является число 16. Поэтому базовый адрес буфера abuf должен быть кратен 16 (четыре младших значащих разряда будут равны нулю). Базовый адрес буфера bbuf будет следовать сразу за адресом последнего элемента буфера abuf. Аналогично будет размещен и буфер cbuf. Размещение всех этих буферов в памяти процессора показано в табл. 11.2.

Таблица 11.2 Размещение трех буферов в памяти процессора

Имя буфера Элемент буфера Двоичный адрес
abuf abuf[0] XXXXXXXXXX0000
abuf[1] XXXXXXXXXX0001
abuf[2] XXXXXXXXXX0010
abuf[3] XXXXXXXXXX0011
abuf[4] XXXXXXXXXX0100
abuf[5] XXXXXXXXXX0101
bbuf bbuf[0] XXXXXXXXXX0110
bbuf[1] XXXXXXXXXX0111
bbuf[2] XXXXXXXXXX1000
cbuf cbuf[0] XXXXXXXXXX1001
cbuf[1] XXXXXXXXXX1010
cbuf[2] XXXXXXXXXX1011
cbuf[3] XXXXXXXXXX1100
XXXXXXXXXX1101

Следующий пример показывает использование трех директив для объявления трех различных кольцевых буферов:

.VAR/CIRC abuf[6];

.VAR/CIRC bbuf[3];

.VAR/CIRC cbuf[5];

Поскольку буферы объявлены отдельно, все они будут кольцевыми и не будут объединены. Правила размещения для каждого из этих буферов такие же, как в рассмотренном выше примере для одиночного буфера abuf. Размещение этих буферов в памяти процессора показано в табл. 11.3.

Таблица 11.3 Размещение трех кольцевых буферов в памяти процессора

Имя буфера Элемент буфера Двоичный адрес
abuf abuf[0] XXXXXXXXX00000
abuf[1] XXXXXXXXX00001
abuf[2] XXXXXXXXX00010
abuf[3] XXXXXXXXX00011
abuf[4] XXXXXXXXX00100
abuf[5] XXXXXXXXX00101
bbuf bbuf[0] XXXXXXXXX01000
bbuf[1] XXXXXXXXX01001
bbuf[2] XXXXXXXXX01010
cbuf cbuf[0] XXXXXXXXX10000
cbuf[1] XXXXXXXXX10001
cbuf[2] XXXXXXXXX10010
cbuf[3] XXXXXXXXX10011

Чтобы получить доступ к буферу abuf из программы, необходимо инициализировать индексные регистры DAG и регистры длины буфера следующими инструкциями:

I0 = ^abuf; {Присвоить индексному регистру I0 базовый адрес буфера abuf}

L0 = %abuf; {Присвоить L0 длину буфера abuf}

M0 = 1; {Присвоить модификатору M0 значение наращивания

 указателя адреса буфера abuf}

Далее в программе можно читать данные из буфера с помощью инструкции AR=DM(I0, L0) или записывать данные в буфер инструкцией DM(I0, L0)=AR. Естественно, вместо регистра AR могут применяться и некоторые другие регистры процессора. При размещении этих инструкций в цикле каждое обращение к буферу будет автоматически увеличивать индексный регистр адреса I0 на величину M0. При достижении регистром I0 величины, равной L0, индексный регистр I0 вновь загрузится базовым адресом буфера. Таким образом, обращения к буферу будут кольцевыми. Для линейных буферов регистр длины буфера должен быть установлен в ноль.

Директивы PMSEG и DMSEG

Данные директивы предназначены для размещения программ и данных в сегментах памяти. Директива PMSEG указывает редактору связей на необходимость разместить все программы и данные модуля в определенном сегменте памяти программ. Директива DMSEG указывает редактору связей на необходимость разместить все структуры данных модуля в определенном сегменте памяти данных. Сегменты должны быть предварительно определены в файле описания архитектуры системного конфигуратора. Директивы PMSEG и DMSEG подобно параметру SEG директив MODULE и VAR имеют следующий формат:

.PMSEG имя_сегмента_pm;

.DMSEG имя_сегмента_dm;

Обычно, чтобы расположить все программы и данные исходного модуля в определенном системным конфигуратором сегменте памяти, необходимо повторить параметр SEG в директиве MODULE и всех директивах VAR внутри модуля. Директивы PMSEG и DMSEG используются для исключения многократного повторения параметров SEG. Директивы PMSEG и DMSEG должны быть размещены в исходном файле программного модуля перед директивой MODULE. Ниже приводится пример, в котором модуль prog1, некоторые буферы и переменную var1 располагают в памяти данных в сегменте с именем seg1:

.DMSEG seg1;

.MODULE/RAM prog1;

.VAR/DM/RAМ/СIRС buf1[15];

.VAR/DM/RAM buf2[5];

.VAR/DM/RAM buf3[5];

.VAR/DM/RAM var1;

...

.ENDMOD;

Директива INIT

Директива INIT используется для инициализации переменных и буферов в ПЗУ. Редактор связей помещает данные инициализации в файл образа памяти, который затем используется разделителем программ (splitter) при подготовке данных для записи в ПЗУ. Разделитель трансформирует части этого файла в формат, совместимый с промышленным стандартом программатора ПЗУ.

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

.INIT имя_буфера: значение1, значение2,...;

.INIT имя_буфера: ^другой_буфер или %другой_буфер,...;

.INIT имя_буфера: <имя_файла>;

Операторы ^ и % используются для инициализации буфера или переменной базовым адресом, или длиной, или даже другими буферами. Любые комбинации констант, указателей адресов буфера и величин длины буфера могут быть заданы через запятую. Примеры:

.INIT x: 0x3FFF;

Данный пример инициализирует переменную x шестнадцатеричной константой 0x3FFF.

.INIT buf: 9,0,3,5,7;

Эта директива инициализирует буфер buf списком констант.

.INIT ab: ^buf;

Здесь переменная ab инициализируется указателем стартового адреса буфера buf.

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

.INIT buf[2]: 3,5,7;

Так, инициализирующие величины будут размещены, начиная с элемента buf[2]. Здесь инициализируются второй, третий и четвертый элементы буфера buf величинами 3, 5 и 7 соответственно.

Третья форма директивы INIT указывает имя файла, который содержит инициализирующие величины. Ассемблер устанавливает указатель на этот файл, и данные присоединяются при запуске редактора связей. Следующий пример заставляет редактор связей инициализировать буфер sin содержимым файла sinus.dat:

.INIT sin: <sinus.dat>;

Если файл с данными находится в директории с программой, то необходимо указать в скобках только имя этого файла. Если файл находится в другом каталоге, необходимо указать путь к этому каталогу и имя файла. Например, если файл init.dat для буфера с именем buff размещен в директории C:\ADSP2181\PROG1\, тогда директива INIT должна быть применена следующим образом:

.INIT buff: <C:\ADSP2181\PROG1\init.dat>

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

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

Переменные данных и буферов могут быть инициализированы с помощью семиразрядного ASCII кода. Следующий пример инициализирует один четырехразмерный буфер input кодами ASCII для букв A, E, F, Z. ASCII коды размещаются в семи младших разрядах 16-разрядной памяти данных или 24-разрядной памяти программ. Символы необходимо заключать в апострофы.

.INIT input: 'AEFZ'; {Инициализировать буфер символами ASCII}

Специальный синтаксис директивы INIT24, позволяет сохранять 24-х разрядные данные в памяти программ. Это дает возможность получить доступ к младшим 8-и разрядам каждого 24-х разрядного слова памяти программ при инициализации буферов данных или переменных в исходной программе.

Например, эта директива позволяет вычислить 16-разрядный адрес для переменной var:

.INIT var: ^buff + 17;

А следующая директива вычисляет 24-разрядный адрес для этой же переменной:

.INIT24 var: ^buff + 17;

Директива GLOBAL

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

.GLOBAL внутренний_символ 1, внутренний_символ 2,...;

Пример:

.VAR/PM/RAM buff[10]; {Создать буфер buff размерностью

 10 элементов}

.GLOBAL buff; {Объявить буфер видимым из других модулей}

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

Директива ENTRY

Директива ENTRY позволяет обращаться к программным меткам в других модулях. Это позволяет использовать метку для вызова подпрограммы или межмодульных переходов. Директива ENTRY имеет формат:

.ENTRY метка 1, метка 2, ...;

Пример:

.ENTRY met; {Делает метку met доступной из других модулей}

С тех пор как метка объявлена директивой ENTRY, другие модули могут обращаться к ней, идентифицируя ее как внешнюю с помощью директивы EXTERNAL.

Директива EXTERNAL

Директива EXTERNAL позволяет программному модулю обращаться к глобальным структурам данных (переменным, буферам и портам) и программным меткам, объявленным в других модулях.

Структура должна быть определена до этого с помощью директивы GLOBAL или ENTRY в тех модулях, где она впервые объявлена. Другие модули должны использовать директиву EXTERNAL для открытия доступа к внешним структурам. Директива имеет формат:

.EXTERNAL структура 1, структура 2, ...;

Пример:

.EXTERNAL met; {Метка находится в другом модуле}

Директива INCLUDE

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

.INCLUDE <имя_файла>;

Если файл, который должен быть включен директивой INCLUDE, находится в текущей директории вместе с программой, в угловых скобках требуется указать только имя файла. Если файл находится в другом каталоге, необходимо указать полный путь к этому каталогу и имя файла (или использовать переменную среды окружения ADII). Например, если файл, который должен быть включен, называется filter.dsp и расположен в директории C:\ADSP2181\PROG2\, тогда директива INCLUDE должна быть задана следующим образом:

.INCLUDE <C:\ADSP2181\PROG2\filter.dsp>;

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

Set ADII=C:\ADSP2181\PROG2

Данная команда должна записываться в файле autoexec.bat операционной системы или в командном файле для трансляции программы. Установка ADII, равной пути к каталогу, позволит ассемблеру обнаружить файл. В этом случае можно задавать имя файла без указания полного пути. Файл, включенный директивой INCLUDE, может также содержать внутри себя директиву INCLUDE. Вложение файлов директивами INCLUDE ограничивается только размером свободной оперативной памяти.

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

Пример:

.INCLUDE <библиотека_макросов>;

Директива MACRO

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

.MACRO имя_макроса (аргумент1, аргумент2, ...);

Завершает макрос директива окончания макроса:

.ENDMACRO;

Каждый оператор внутри макроса может быть инструкцией, директивой или макровключением. Макрос вызывается по своему имени. Чтобы выполнить макрос с именем mac1, необходимо вставить в текст программы команду mac1;. Макровызов не должен содержать дополнительных операторов в строке вызова (т.е. инструкций, директив препроцессора или других макровключений).

Аргументы макроса имеют форму записи:

%n, где n = 0, 1, 2, …, 9;

Следующий пример определяет макрос sum с тремя аргументами:

.MACRO sum(%0, %1, %2);

В коде макроса аргументы маркируются служебными символами %1, %2, %3, и т.д. При вызове макроса служебные символы замещаются величинами аргументов, переданных в макрос. При вызове макроса ему должно быть передано правильное число аргументов. Допустимые передаваемые аргументы и исключения для них приведены в табл. 11.4.

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

Аргумент Исключение
Константа или арифметическое выражение Нет
Символы MACRO, ENDMACRO, CONST, INCLUDE
^буфер ^%n
%буфер %%n

Операторы ^ и % не могут быть использованы с аргументами, замещающими служебные символы в макроопределении. Тем не менее, аргументы, переданные в макрос, могут использовать эти операторы. Например: read_data(^input);

Директива LOCAL

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

.LOCAL метка1, метка2, ...;

Ассемблер создает уникальные версии меток макроса, добавляя к ним номер. Это можно увидеть в файле листинга с расширением lst. Помните, что для раскрытия макросов в листинге необходимо при запуске программы компилятора asm21 добавить ключ -m.

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

.MACRO nops;

nop; nop; nop; nop; nop; nop;

.ENDMACRO;

Вызов данного макроса в программе осуществляется командой nops;. Следующий пример показывает, как создать макрос wait с одним параметром и одной локальной меткой.

MACRO wait(%0);

 local loop;

 cntr=%0;

 do loop until ce;

 loop: nop;

ENDMACRO;

Этот макрос позволяет организовать в программе функцию задержки на 100 циклов лаконичной записью:

wait(100);

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

Ниже приведен пример макроса, реализующий подпрограмму, которая переносит содержимое буфера данных из одной области памяти в другую.

.MACRO mem_trans (%0, %1, %2, %3, %4) {Использует 5 аргументов}

.LOCAL trans;

I4=%0; {Установить I4 как адрес источника}

I5=%1; {Установить I5 как адрес приемника}

M4=1 {Установить указатель на инкремент 1}

CNTR=%2 {Установить длину буфера}

DO trans UNTIL СЕ; {Перенос данных}

si=%3(I4, M4) {Перенос данных из типа %3 памяти}

trans: %4(I5, M4)=si; {В тип %4 памяти}

.ENDMACRO

Пример вызова этого макроса в программе может быть таким:

mem_trans (^tabl_coef, ^buf, %buf, PM, DM);

Здесь в качестве аргументов в макрос передаются адреса буферов tabl_coef и but, длина буфера but и тип памяти. Заметьте, что зарезервированные ключевые слова PM и DM переданы как аргументы.

Несколько следующих директив определяют формат файла листинга. Файл листинга с расширением lst позволяет представить результаты процесса ассемблирования. Ниже показан пример файла листинга простейшей программы. В этом файле используются следующие информационные поля:

addr — смещение от базового адреса модуля;

inst — код операции;

source line — номер строки исходного файла и код.

Release 5.11 Assembler Version 1.34s 9/19/95

D:\TEMA\IKS\PROG\TEST.DSP\DOS.dsp Mon Jun 21 17:07:36 2004 Page 1

addr inst     source line

              1 .module/RAM/ABS=0 example;

              2 .PAGEWIDTH 70;

              3 {Описание переменных}

              4 .var/dm flag;

              5

              6 {Инициализация переменных}

              7 .init flag: 0x000f;

              8

              9 again:

0000 02010F  10 toggle FL1; /* Инвертировать флаг */

0001 18000Fu 11 jump again; /* Зациклить */

             12 .endmod;

Каждая строка в листинге этой программы имеет свой номер. При обнаружении ошибки в какой-либо строке программы компилятор выдает именно этот номер строки. Символ «u» в поле inst показывает, что код операции содержит адрес перехода.

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

Директива NEWPAGE

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

.NEWPAGE;

Директива PAGELENTH

Директива PAGELENTH регулярно вставляет разделитель страниц после указанного количества строк. Формат ее записи:

.PAGELENGTH число_строк;

Директива LEFTMARGIN

Директива LEFTMARGIN оставляет левое поле с указанным числом столбцов (знакомест символов). Формат ее записи:

.LEFTMARGIN число_столбцов;

Директива INDENT

Директива INDENT осуществляет отступ строк программы в исходном коде с указанным числом столбцов. Формат ее записи:

.INDENT число_столбцов;

Директива PAGEWIDTH

Директива PAGEWIDTH определяет ширину строк листинга с указанным числом столбцов. Формат ее записи:

.PAGEWIDTH число_столбцов;

Директивы NEWPAGE и PAGELENGTH могут быть использованы для нумерации страниц, в то время как директивы LEFTMARGIN, INDENT и PAGEWIDTH используются для того, чтобы сделать каждую страницу удобной для чтения. Эти директивы могут быть помещены в любом месте исходного файла.

Директива ENDMOD

Директива ENDMOD указывает на завершение программного модуля. Программа ассемблера останавливается, когда достигает директивы ENDMOD. Формат ее записи:

.ENDMOD;