Руководство пользователя по сигнальным процессорам Sharc
.pdf
Линк-порты 9
DRAM 0 |
|
|
|
|
|
|
20 МГц |
|
ASIC |
L0DAT |
|
|
ADSP-2106x |
|
16 |
3-0 |
|
|
||
данные |
интерфейс с |
L0CLK |
|
|
|
|
|
|
|
|
|||
адрес |
|
линк-портом |
L0ACK |
|
|
|
|
|
6 |
|
|
линк-порт 0 |
|
и |
|
|
|
|
||
|
|
|
|
|
||
управление |
|
тактовая частота |
|
0 |
|
внешний |
|
|
|
оп-р та |
троа 1 |
порт |
|
|
|
|
|
линк-порт 1 |
||
|
|
|
|
к |
п |
|
DRAM 1 |
|
|
|
илн |
ник- |
|
|
|
|
|
|
|
|
20 МГц |
|
|
|
а |
л |
ADSP-2106x |
16 |
ASIC |
|
Ши н |
ниа |
|
|
|
|
|
||||
данные |
|
интерфейс с |
|
|
Ш |
|
|
линк-портом |
|
|
|
||
|
|
|
|
|
|
|
адрес |
|
|
|
|
|
линк-порт 0 |
и |
|
|
|
6 |
|
внешний |
управление |
|
тактовая частота |
|
|
|
|
|
L1DAT |
|
|
порт |
||
|
|
|
3-0 |
|
линк-порт 1 |
|
|
|
|
L1CLK |
|
|
|
|
|
|
L1ACK |
|
|
|
Рис. 9.8. Локальная DRAM и линк порты
Устройство ввода-вывода
Внешняя память
Устройство DMA
Хост-процессор
Обращение к DRAM через линк порт наиболее эффективно под управлением DMA. ASIC принимает управляющую информацию DMA из линк порта и настраивает доступ к DRAM. Она распаковывает 16 разрядные слова данных из DRAM или упаковывает 4 разрядные полубайты из линк порта. Прерывание в конце передачи по DMA позволяет ADSP 2106x послать новую управляющую информацию в ASIC. ASIC всегда возвращается в режим приема в конце передачи. Сигнал LxACK сбрасывается ASIC, как только происходит изменение страницы, цикл обновления памяти или любой другой доступ к DRAM.
Модули памяти могут совместно использоваться несколькими ADSP 2106x, когда линк порт подключен к общей шине. Каждый линк порт поддерживает производительность доступа 40 Мбайт для команд и данных. ASIC отвечает за генерацию удвоенной тактовой частоты при передаче в ADSP 2106x. ASIC также отвечает за генерацию последовательных адресов DMA на основании начального адреса и счетчика слов.
9.11 Примеры программирования
Листинги 9.1 и 9.2 иллюстрируют два способа выполнения передачи данных через линк порт.
331
9 Линк-порты
9.11.1. Передача одного слова данных, управляемая ядром
В листинге 9.1 приведен пример передачи одного слова данных, управляемой ядром процессора ADSP 2106x.
9.11.2. Передача по DMA
В листинге 9.2 приведен пример программы передачи данных по DMA.
Листинг 9.1. Пример управляемой ядром передачи
/*__________________________________________________________________________
Пример управляемой ядром передачи через линк-порт в циклическом режиме.
В этом примере показана внутренняя передача с использованием линк-порта в циклическом режиме. Ядро выполняет прямую запись в передающий буфер линкпортов (LBUF3) и прямое чтение из приемного буфера (LBUF2). Ядро зависнет при чтении LBUF2, пока данные не будут готовы. Цикличность достигается при помощи назначения приемному и передающему буферам линк-портов одного и того же порта (Port 0).
________________________________________________________________________________*/
#include “def21060.h”
.segment/pm rst_svc; /* Вектор сброса из файла архитектуры */
nop; |
/* Первая ячейка используется для начальной загрузки */ |
jump |
start; |
.endseg;
/*_______________________________основная программа ______________________*/
.segment/pm pm48_1b0; /*основной сегмент кода из файла архитектуры */
start: |
|
r0=0x0000c000; |
/* Регистр LCOM: удвоенная частота */ |
dm(LCOM)=r0; |
/* Замечание: используйте r0=0x00010000 для версии */ |
|
/* кристалла 0.х */ |
r0=0x0003f03f; |
/*Регистр LAR: LBUF2->Port0, LBUF3->Port0 */ |
dm(LAR)=r0; |
/*Все остальные неактивны */ |
r0=0x00009100; |
/*Регистр LCTL: 32-разрядные данные, LBUF2=rx, LBUF3=tx */ |
dm(LCTL)=r0; |
/* Всегда записывайте LCTL после LAR */ |
r0=0x12345678; |
/*Проверка данных для передачи */ |
dm(LBUF3)=r0; |
/*Запись в LBUF3 для передачи */ |
r1=dm(LBUF2); /*Чтение ядра зависнет здесь, пока данные не будут приняты */
wait: jump wait;
.endseg;
332
Линк-порты 9
Листинг 9.2. Пример передачи по DMA
/*__________________________________________________________________________
Пример передачи ADSP-2106x через линк-порт в циклическом режиме под управлением DMA.
В этом примере показана внутренняя передача с использованием линк-порта в циклическом режиме. Буфер 3 линк-портов (LBUF3) и соответствующий 5 канал DMA используются для передачи. Буфер 2 линк-портов (LBUF2) и соответствующий 5 канал DMA используются для приема. Прерывание LBUF2 сгенерируется, когда передача по DMA будет выполнена. Цикличность достигается назначением приемному и передающему буферам линк-портов одного и того же порта (Port 0).
_____________________________________________________________________________*/
#define N 8
#include “def21060.h”
.segment/dm dm32_b1; /*Имя сегмента данных описано в файле архитектуры */
.var source[N] = 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888;
.var destination[N];
.endseg;
.segment/pm rst_svc; /* Вектор сброса из файла архитектуры */ nop; /* Первая ячейка памяти используется для */
/* начальной загрузки */ jump start;
.endseg;
.segment/pm lp2_svc; /* Вектор прерывания буфера 2 линк-портов */ jump lp2rx;
.endseg;
/*__________________________основная программа ___________________________*/
.segment/pm pm48_1b0; /* Основной сегмент кода из файла архитектуры */
start: |
|
r0=source; |
|
dm(II5)=r0; |
/* Установка индекса DMA на начало буфера источника */ |
r0=destination; |
|
dm(II4)=r0; |
/*Установка индекса DMA на начало буфера адресата */ |
r0=1; |
|
dm(IM5)=r0; |
/*Установка модификатора DMA (шаг) в 1 */ |
dm(IM4)=r0; |
|
r0=@source; |
|
dm(C5)=r0; |
/*Установка счетчика DMA в соответствии*/ |
|
/* с длиной буфера данных */ |
dm(C4)=r0; |
|
r0=0x0000c000; |
/*Регистр LCOM: удвоенная частота */ |
333
9 Линк-порты
dm(LCOM)=r0; |
/*Замечание: используйте r0=0x00010000 для версии */ |
/* кристалла 0.х */ |
|
r0=0x0003f03f; |
/* Регистр LAR: LBUF2-> Port0, LBUF3-> Port0 */ |
dm(LAR)=r0; |
/* Все остальные неактивны */ |
r0=0x0000b300; |
/* Регистр LCTL: 32-разрядные данные, LBUF2=rx, LBUF3=tx */ |
dm(LCTL)=r0; |
/* Разрешение DMA в LBUF2 и LBUF3 */ |
/*Это начало передачи по DMA */
/* Всегда записывайте LCTL после LAR */
bit set imask LP2I; /* Разрешение прерывания буфера 2 линк-портов */ bit set mode1 IRPTEN; /* Глобальное разрешение прерываний */
wait: idle; |
/* Ожидание прерывания буфера 2 линк-портов */ |
jump wait; |
/* Здесь окончание после выполнения DMA */ |
/*____Программа обработки прерывания буфера 2 линк-портов при приеме _____*/
lp2rx: rti; |
/* Это прерывание произойдет только один раз */ |
.endseg;
Листинг 9.3. Пример связи через линк-порт с передачей маркера
/*__________________________________________________________________________
Пример связи через линк-порт с передачей маркера.
Это пример программного протокола для кольцевой передачи маркера через линкпорт, используя LSRQ. Этот код загружается и в первоначально ведущего, и в первоначально ведомого. Код идентификатора (ID) является значимым в многопроцессорной системе: ID1 – это первоначальный ведущий (передатчик), ID2 – первоначальный ведомый (приемник). Ведущий передает буфер посредством DMA через LPORT0, используя LBUF3, а ведомый принимает через LPORT0, используя LBUF2. Затем ведомый запрашивает маркер, генерируя прерывание LSRQ в заблокированном линк-порту ведущего (LPORT0). Ведущий посылает слово освобождения маркера и ждет, пока оно не будет принято. Ведомый проверяет, является ли оно словом освобождения маркера и принимает маркер, освобождая FIFO буфер линк-портов ведущего в течение определенного времени. Если маркер принят, ведомый становится ведущим и передает блок данных из буфера новому ведомому. Если маркер не принят, первоначальный ведущий будет передавать второй блок данных из буфера. По окончании выполнения первоначальный ведущий настраивает LBUF2 на прием без DMA, первоначальный ведомый настраивает LBUF3 на передачу без DMA. FLAG0 используется как программный флаг, чтобы указать первоначально ведущего.
_____________________________________________________________________________*/
#include “def21060.h”
#define N 8 |
/*Размер буфера */ |
334
Линк-порты 9
#define trw 0x0 |
/*Слово освобождения маркера */ |
#define orig_master_id 1 /*ID SHARC, который будет первоначальным ведущим */ #define orig_slave_id 2 /*ID SHARC, который будет первоначальным ведомым */
.SEGMENT/DM dm_data;
.var source_1[N]= 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x11111111, 0x22222222, 0x33333333, 0x44444444;
.var source_2[N]= 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x55555555, 0x66666666, 0x77777777, 0x88888888;
.var source_3[N]= 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888;
.var destination_1[N];
.var destination_2[N];
.var destination_3;
.ENDSEG; |
|
|
.SEGMENT/PM isr_tabl; |
/*Таблица обработки прерывания */ |
|
NOP; NOP;NOP;NOP; |
/*Зарезервированное прерывание */ |
|
rst_svc: |
nop; jump start; nop; nop; |
|
NOP; NOP; NOP; NOP; |
|
|
sovfi_svc: |
RTI; RTI; RTI; RTI; |
|
tmzhi_svc: |
rti; RTI; RTI; RTI; |
|
vrpti_svc: |
RTI; RTI; RTI; RTI; |
|
irq2_svc: |
rti; RTI; RTI; RTI; |
|
irq1_svc: |
rti; RTI; RTI; RTI; |
|
irq0_svc: |
rti; RTI; RTI; RTI; |
|
NOP; NOP; NOP; NOP; |
|
|
spr0_svc: |
RTI; RTI; RTI; RTI; |
|
spr1_svc: |
RTI; RTI; RTI; RTI; |
|
spt0_svc: |
RTI; RTI; RTI; RTI; |
|
spt1_svc: |
RTI; RTI; RTI; RTI; |
|
lp2_svc: |
nop; jump lp2; nop; nop; |
|
lp3_svc: |
nop; jump lp3; nop; nop; |
|
ep0_svc: |
RTI; RTI; RTI; RTI; |
|
ep1_svc: |
RTI; RTI; RTI; RTI; |
|
ep2_svc: |
RTI; RTI; RTI; RTI; |
|
ep3_svc: |
RTI; RTI; RTI; RTI; |
|
lsrq_svc: |
nop; jump lsrq; nop; nop; |
|
cb7_svc: |
RTI; RTI; RTI; RTI; |
|
cb15_svc: |
RTI; RTI; RTI; RTI; |
|
tmzl_svc: |
rti; RTI; RTI; RTI; |
|
.ENDSEG;
335
9 Линк-порты
/*____________________________основная программа _________________________*/
.SEGMENT/PM pm_code;
start: |
|
|
|
|
bit |
set mode2 FLG0Î; |
/* Установка Flag0 |
как выходного сигнала */ |
|
bit |
clr astat FLG0; |
/*Сброс Flag0 для |
åãî |
использования в качестве флага */ |
|
|
/* проверки, является ли этот SHARC */ |
||
|
|
/*первоначально |
ведущим */ |
|
r0=dm(SYSTAT);
r0=FEXT r0 BY 8:3; /* Извлечение процессорного ID из SYSTAT */
r1=orig_master_id; |
|
|
r1=r0-r1; |
/*Проверка, является ли этот SHARC первоначальным */ |
|
if eq jump start_as_master; |
/* ведущим и соответственно переход */ |
|
r1=orig_slave_id; |
|
|
r1=r0-r1; |
/* Проверка, является ли этот SHARC первоначальным */ |
|
if eq jump start_as_slave; |
/* ведомым и соответственно переход */ |
|
idle; |
|
|
nop; |
|
|
/*_________Начало |
программы |
первоначально ведущего __________________*/ |
start_as_master:
bit set astat FLG0; /*Установка Flag0, чтобы обозначить первоначально */
|
/* |
ведущего */ |
r0=source_1; |
|
|
dm(II5)=r0; |
/*Установка индекса DMA на начало буфера источника */ |
|
r0=1; |
|
|
dm(IM5)=r0; |
/*Установка модификатора DMA (шаг) в 1 */ |
|
r0=@source_1; |
|
|
dm(C5)=r0; |
/*Установка счетчика DMA в соответствии /* |
|
/*с длиной буфера данных */ |
||
r0=0xc000; |
|
/*Регистр LCOM: удвоенная частота в LBUF3 */ |
dm(LCOM)=r0; |
/* замечание: используйте r0=0x00010000 для версии */ |
|
/*кристалла 0.х */ |
|
|
r0=0x3f1ff; |
/* Регистр LAR: LBUF3->Port0 */ |
|
dm(LAR)=r0; |
/* Все остальные неактивны */ |
|
bit set imask LP3I; |
/* Разрешение прерывания буфера 3 линк-портов */ |
|
bit set mode1 IRPTEN; |
/* Глобальное разрешение прерываний */ |
|
r0=0x0000b000; |
/* Регистр LCTL: 32-разряднве данные, LBUF3=tx */ |
|
dm(LCTL)=r0; |
/*Разрешение DMA в LBUF3 */ |
|
/*Это – начало передачи по DMA */ |
||
/* Всегда записывайте LCTL после LAR */ |
||
wait_1: idle; |
/* Ожидание прерывания буфера 2 линк-портов */ |
|
336
Линк-порты 9
jump |
wait_1; |
/* Здесь окончание после выполнения DMA |
*/ |
nop; |
|
/* Все прерывания ведущего возвращаются |
ñþäà */ |
nop; |
|
|
|
/*_________Программа обработки прерывания буфера 3 линк-портов ___________*/
lp3:
if NOT FLAG0_IN jump lp3_orig_slave; /*Проверка для первоначально */
/* ведущего и соответственно переход */
nop;
nop;
/*_____Конец программы обработки прерывания буфера 3 линк-портов _________*/
lp3_orig_master:
/*__Разрешение задержки «подтягивания» к земле на выводе LxACK ведомого __*/
bit clr imask LSRQI;/*Запрещение прерывания запроса обслуживания линк-порта*/
r0=0x10;
dm(LSRQ)=r0; /*Демаскирование состояния запроса передачи lport0 в LSRQ */
r0=0x00000000; |
|
|
dm(LCTL)=r0; |
/* LCTL: блокировка всех LBUF */ |
|
disabled1: |
|
|
r0=dm(LSRQ); |
|
/*Проверка, чтобы гарантировать, что LxACK сброшен*/ |
/*с помощью «подтягивающего» к земле резистора на его выводе */ |
||
r0=FEXT r0 BY 20:1; |
/*. И первоначально ведущий, и */ |
|
r0=pass r0; |
|
/* ведомый будут синхронизированы */ |
if NE jump disabled1; |
/* Следующее выставление LxACK будет указывать */ |
|
/*ведущему, что ведомый запрашивает маркер */
/*________________________________________________________________________*/
r0=0x00000000;
dm(LCTL)=r0; /*Запрещение всех LBUF */
bit set imask LSRQI; /*Разрешение прерывания запроса обслуживания*/ /*линк-порта */
r0=0x10;
dm(LSRQ)=r0; /* Демаскирование состояния запроса передачи lport 0 в LSRQ */
rti;
/*______Конец программы обработки прерывания буфера 2 линк-портов ________*/
337
9 Линк-порты
lp3_orig_slave:
/* Окончание установкой LBUF3 без DMA */
bit clr imask LP3I; |
/* Запрещение прерывания буфера 2 линк-портов */ |
r0=0x3f1ff; |
|
dm(LAR)=r0; |
/*Регистр LAR: LBUF3->Port 0 */ |
r0=0x00009000; |
|
dm(LCTL)=r0; |
/* Разрешение LBUF3 без DMA */ |
rti; |
|
/*_____Программа обработки прерывания запроса обслуживания линк-порта ____*/
lsrq: |
|
|
|
bit clr imask LP3I; |
/*Запрещение прерывания буфера 3 линк-портов */ |
||
r0=0x00009000; |
|
/* Регистр LCTL:32-разрядные данные, */ |
|
/* LBUF3 настроен для передачи */ |
|
||
dm(LCTL)=r0; |
|
/*Запрещение DMA в LBUF3 */ |
|
r0=trw; |
/*Взятие слова освобождения маркера */ |
||
dm(LBUF3)=r0; |
/*Посылка слова освобождения маркера, чтобы ведомый */ |
||
dm(LBUF3)=r0; |
/* заполнил FIFO линк-порта ведущего и ведомого, */ |
||
dm(LBUF3)=r0; |
/*записывая четыре раза и оставляя FIFO */ |
||
dm(LBUF3)=r0; |
/*полностью заполненными с обеих сторон */ |
||
token_read: |
|
|
|
r1=0x40; |
/*Проверка, считал ли ведомый маркер */ |
||
r0=dm(LCOM); |
/* Проверка, считал ли ведомый первое слово, */ |
||
r0=r0 AND r1; |
/*чтобы убедиться, что они синхронизированы для */ |
||
if NE jump token_read; |
/*проверки возврата маркера */ |
||
LCNTR=10, DO wait_for_slave UNTIL LCE; |
|
||
wait_for_slave: nop; |
/* ведомому дается время для принятия или */ |
||
/* возврата маркера */ |
|
||
r1=0xc0; |
|
/*Проверка, запрашивал ли ведомый маркер */ |
|
r0=dm(LCOM); |
|
/*Проверка, освободил ли ведомый FIFO */ |
|
r0=r0 AND r1; |
|
/*в течение 10 циклов, */ |
|
if NE jump second_master_mode; /*иначе второй в режиме ведущего */
slave_mode:
/*_________Защита от одновременной передачи двумя линк-портами ___________*/
bit clr imask LSRQI; /*Запрещение прерывания запроса обслуживания линкпорта*/
338
Линк-порты 9
r0=0x10;
dm(LSRQ)=r0; /* Демаскирование состояния запроса передачи lport0 в LSRQ */
r0=0x00000000; |
|
dm(LCTL)=r0; |
/* LCTL: блокировка всех LBUF */ |
slave_disabled: |
|
r0=dm(LSRQ); |
/* Проверка, чтобы убедиться, что первоначальный */ |
r0=FEXT |
r0 BY 20:1; /* ведомый сейчас блокирован. Если блокирован, */ |
|
r0=pass |
r0; |
/* то сброс LxACK и остановка генерации LxTRQ */ |
if NE jump slave_disabled;
/*________________________________________________________________________*/
r0=0x3fe3f; |
|
dm(LAR)=r0; |
/*Регистр LAR: LBUF2->Port 0 */ |
r0=0x00000100; |
|
dm(LCTL)=r0; |
/* LCTL: разрешение LBUF2, без DMA */ |
r0=dm(LBUF2); |
/* Считывание размера блока, передаваемого по DMA */ |
dm(C4)=r0; |
/* Установка счетчика DMA равным длине буфера данных */ |
r0=destination_3; |
|
dm(II4)=r0; |
/*Установка индекса DMA на начало буфера назначения */ |
r0=1; |
|
dm(IM4)=r0; |
/*Размер шага */ |
r0=0x00000300; |
|
dm(LCTL)=r0; |
/*Разрешение DMA LBUF2 */ |
bit clr irptl LP2I;/*Очистка отложенного прерывания буфера 2 линк-портов */ bit set imask LP2I; /*Разрешение прерывания буфера 2 линк-портов */
bit set mode1 IRPTEN; /* Глобальное разрешение прерываний */
rti;
second_master_mode:
token_read2: |
|
|
r1=0xC0; |
/* Проверка, считал ли |
ведомый маркер */ |
r0=dm(LCOM); |
/*Проверка, освободил ли ведомый FIFO,*/ |
|
r0=r0 AND r1; |
/*чтобы убедиться, что |
они синхронизированы для */ |
if NE jump token_read2; |
/*второй передачи по DMA */ |
|
r0=0x3fe3f; |
|
|
dm(LAR)=r0; |
/*Регистр LAR: LBUF2->Port 0*/ |
|
339
9 Линк-порты
r0=0x00000900; |
|
dm(LCTL)=r0; |
/*Разрешение LBUF2 без DMA */ |
r0=@source_2; |
|
dm(LBUF2)=r0; |
/*Размер буфера DMA для ведомого */ |
r0=source_2; |
|
dm(II4)=r0; |
/* Установка индекса DMA на начало буфера источника */ |
r0=1; |
|
dm(IM4)=r0; |
/*Установка модификатора DMA (шага) в 1 */ |
r0=@source_2; |
|
dm(C4)=r0; |
/* Установка счетчика DMA равным длине буфера данных */ |
r0=0x00000b00; |
/*Регистр LCTL: 32-разрядные данные, LBUF2=tx */ |
dm(LCTL)=r0; |
/*Разрешение DMA в LBUF2 */ |
/*Это – начало передачи по DMA */
/* Всегда записывайте LCTL после LAR */
bit clr irptl LP2I; /*Очистка отложенного прерывания буфера 2 линк-портов */ bit set imask LP2I; /* Разрешение прерывания буфера 2 линк-портов */
bit set mode1 IRPTEN; /* Глобальное разрешение прерываний */
rti;
/*______________Программа прерывания буфера линк-портов 2 _______________*/
lp2:
if NOT FLAG0_IN jump lp2_orig_slave; /*Проверка для первоначально */ nop; /* ведущего и соответственно переход */ nop;
/*___Окончание программы обработки прерывания Rx буфера 2 линк-портов ____*/
lp2_orig_master: |
/*Окончание, настройка LBUF2 без DMA */ |
|
r0=0x3fe3f; |
|
|
dm(LAR)=r0; |
|
/*Регистр LAR: LBUF2->Port 0 */ |
r0=0x00000100; |
|
|
dm(LCTL)=r0; |
|
/*Разрешение LBUF2 без DMA */ |
rti; |
/*Это прерывание произойдет только один раз */ |
|
340
