Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DSP-A5-new.DOC
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
298.5 Кб
Скачать

9.Сдача работы:

Показать рисунок с графиком.

10.После работы с С-компилятором перевести «VisualDSP» в режим

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

«VisualDSP», создать новый проект, указать другой файл 2189ezkit.ldf

из папки для работы номер 2. Если это не помогает, проверьте текст

введенной программы. Забытая «;» в конце оператора зачастую приводит

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

Работа номер 2

Основы архитектуры ADSP-21xx

Литература: "ASM_Commands.pdf", "DSP_ASM.pdf"

Основные регистры процессора, используемые в данной работе:

АX0 - регистр общего назначения;

АY0 - регистр общего назначения;

AR - регистр результата АЛУ;

I0 - индексный регистр;

M0 - регистр - модификатор;

L0 - регистр длины (циклического буфера).

Все регистры процессора продублированы, это позволяет оперативно

менять набор регистров, например, при обработке прерываний:

ENA SEC_REG; // работа со 2 банком регистров

DIS SEC_REG; // работа с 1 банком регистров

Комментарии в ассемблерных программах такие же, как в С.

Каждая команда заканчивается точкой с запятой.

DSP семейства 21хх имеют два типа памяти. Программная память имеет разрядность 24 бита, память данных - 16 бит на слово. Для работы с памятью имеются генераторы адреса.

DAG1 (Data Address Generator) обслуживает только память данных.

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

Обращение к памяти имеют след.вид:

AX0=PM(address); // direct чтение из programm memory

AY0=DM(address); // direct чтение из data memory

Доступ к памяти через индексные регистры:

L0=0;// длина буфера, если он циклический, для нециклического зануляется

AX0=PM(I0,M0); // после операции I0=I0+M0 ( модификация адреса)

AY0=DM(I1,M1);

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

AR=AX0+AY0, AX0=PM(a1), AY0=DM(a2); // делается за 1 цикл

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

Для работы необходимо знать некоторые битовые флаги , которые

имеют процессоры серии 21хх.

Флаг CE уставляется, если счетчик цикла(CNTR) равен 0;

Нижеследующие флаги уставляются после АЛУ операций или операции

проверки.

NE - не равно 0

EQ - равно 0

Использование флагов:

IF NE AR=AX0+AY0; // не равно 0

IF EQ AR=константа; // равно 0

Операция анализа флага и основная операция делаются за 1 цикл.

Константа в коде операции может быть только степенью 2.

Команды, необходимые для выполнения работы:

label: NOP; // нет операции, 1 цикл, label - метка для call/jump

RTI; // возврат из прерывания

RTS; // возврат из процедуры

JUMP label; // переход

If cond jump label;// условный переход

TOGGLE bit; //смена состояния бита

TOGGLE FL1; // смена состояния бита FL1

Бит FL1 соединен со светодиодом на плате EZ-KIT.

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

тип памяти и все атрибуты программной секции. Эта информация

содержится в Linker file.

Приведем некоторые описания секций из файла 2189ezkit.ldf.

// Сегмент векторов прерываний

seg_rth { TYPE(PM RAM) START(0x00000) END(0x0002F) WIDTH(24) }

// Секция для кода программы

seg_code { TYPE(PM RAM) START(0x00030) END(0x01840) WIDTH(24) }

// Секция данных в памяти данных

seg_data{ TYPE(DM RAM) START(0x00000) END(0x036AF) WIDTH(16)}

// Еще одна секция для кода или данных в памяти программ

seg_code2{ TYPE(PM RAM) START(0x02000) END(0x02600) WIDTH(24)}

При написании программы необходимо указывать секцию в виде

.section/pm seg_rth;

здесь .seсtion/pm – указание на тип памяти

seg_rth – название секции, определенное в файле 2189ezkit.ldf.

Секция векторов прерываний, которая должна быть в каждой программе,

выгядит след.образом:

.section/pm seg_rth; // вектора прерываний

JUMP start; NOP; NOP; NOP; /* reset 0x00 */

RTI; NOP; NOP; NOP; /* IRQ2 0x04 */

RTI; NOP; NOP; NOP; /* IRQ1L 0x08 */

RTI; NOP; NOP; NOP; /* IRQL0 0x0C */

JUMP P0_tx; NOP; NOP; NOP; /* SPORT0_TX */

JUMP P0_rx; NOP; NOP; NOP; /* SPORT0_RX */

RTI; NOP; NOP; NOP; /* IRQE 0x18 */

RTI; NOP; NOP; NOP; /* BDMA 0x1C */

RTI; NOP; NOP; NOP; /* SPORT1 TX 0x20 */

RTI; NOP; NOP; NOP; /* SPORT1 RX 0x24 */

NOP; NOP; NOP; RTI; /* !!!! именно так - timer 0x28 */

RTI; NOP; NOP; NOP; /* POWERDOWN 0x2C */

Таблица векторов прерываний начинается с 0 адреса памяти программ,

каждый вектор состоит из четырех слов.

0 вектор исполняется при старте (reset) программы.

Таймер используется программой-монитором, поэтому у него первым

оператором идет NOP, затем две ячейки, куда заносится служебная

информация для работы монитора, и оператор RTI.

Задание - найти адреса векторов SPORT0.

.section/dm seg_data; // константы и переменные в data memory

.var v1=131;

.var v2=2222;

.section/pm seg_code; // код программы

start: // метка начала

ax0=DM(v1);

Значение констант в данном случае может быть любым.

Процессор имеет специальный регистр CNTR для организации циклов.

Цикл организуется командой

DO label UNTIL CE;

В тело цикла входят все команды после команды DO до команды,

помеченной меткой label, включая и саму помеченную команду.

CNTR=10; // цикл выполнится 10 раз

DO L1 UNTIL CE; // начало цикла

AR=AX0+AY0; // первая команда в цикле

…… // другие команды в цикле

L1:TOGGLE FL1; // последняя (помеченная меткой L1) команда цикла,

//после нее происходит автоматический декремент CNTR, проверка флага

//CE и переход на начало цикла, если CE не уставлен.

Пример вложенного цикла

CNTR=5000;//задать значение счетчика;

DO label0 UNTIL CE;// Выполнять цикл до исчерпания в,каждом цикле

//счетчик декрементируется

CNTR=1000; // начало вложенного цикла, предыдущее значение

//счетчика прячется в стек

DO label1 UNTIL CE; // первое значение счетчика спрятано в стек

label1: ar=ax0-ay0; // второй (вложенный) цикл, выполняется

// 1000 раз на один проход внешнего цикла

// восстановление счетчика из стека после вложенного цикла

// делается автоматически

label0: AR=ax0+ay0; // команда первого (основного) цикла

Из-за вложенности команда, помеченная меткой label1, выполнится

5000*1000=5000000 раз.

Добиться этого заданием значения CNTR нельзя, т.к. он 16-битный.

Автоматическoe сохранение/восстановление регистра CNTR обеспечивает

вложенность до четырех циклов DO.

Задание 2.1 Программа мигания светодиодом.

1.Создать проект для 2189 процессора (см. работу номер 1).

2.Создать файл-asm и включить в проект. Включить в проект Linker file

2189ezkit.ldf

3.Задать таблицу векторов в секции seg_rth:

section/pm seg_rth;

JUMP start; NOP; NOP; NOP; /* reset 0x00 - первая строка таблицы*/

остальные 10 строк:

RTI; NOP; NOP; NOP;

кроме таймера:

NOP; NOP; NOP; RTI; /* !!!! именно так - timer 0x28 */

4. Написать программу в секции section/pm seg_code.

Бит FL1 соединен со светодиодом на плате EZ-KIT.

TOGGLE FL1; // смена состояния бита FL1

Цикл процессора - 13.3 нсек, для замедления используйте оператор DO. Для заметного на глаз мигания светодиода используйте как минимум два вложенных цикла.

Сдача задания 2.1:

1-Найти адреса векторов SPORT0.