2.1.3.Модели памяти Все функции библиотеки предполагают использование дальних указателей типа FAR, как для вызова процедур, так и для передачи адресов данных, поэтому компиляцию программы в языке С++ желательно проводить в модели памяти LARGE, в которой по умолчанию используются дальние вызовы процедур и дальние указатели на данные.
2.1.4.Общий подход к работе с платами серии L7xx На сегодняшний момент времени существуют следующие разновидности плат серии L7xx:
платы L-761 (Rev. B);
платы L-780 (Rev. A), L-780 (Rev. B) и L-780 (Rev. С);
платы L-783 (Rev. B).
2.1.4.1.Особенности работы плат “L-780” через порты Платы L-780 могут быть трех разновидностей: ревизия ‘A’, ревизия ‘B’ и ревизия ‘C’ (поле BoardRevision в структуре BOARD_INFO см. § 2.1.5.1.1 “Структура BOARD_INFO”). Их различие состоит в том, что платы ревизии ‘A’ требуют для своей работы под DOS большее количество ресурсов в виде портов и, в связи с этим, на некоторых материнских платах не функционируют должным образом. Для исключения этого эффекта использование портов на плате, т.е. доступ к плате через порты ввода-вывода, можно полностью запретить с помощью утилиты \Utils\CHIOMEM\CHIOMEM.EXE (подробности см. в приложении C). По умолчанию платы ревизии ‘A’ выпускаются с запрещенным доступом через порты I/O. Значение базового порта I/O для доступа к плате после выполнения API-функции INIT_ACCESS_TO_PLX() находится в поле IO_BaseAddress структуры BOARD_INFO (см. § 2.1.5.1.1 “Структура BOARD_INFO”).
2.1.4.2.Особенности работы плат L7xx через память ниже 1 Мб Все платы серии L7xx дают пользователю возможность работы с ними как через порты ввода-вывода (традиционный подход), так и через память, которая расположена либо в диапазоне от 640 Кб до 1 Мб, либо где-нибудь выше 1 Мб. Под работой через память подразумевается работа с платой, когда все ее управляющие регистры “отображены” на обычную память РС и доступ к ней возможен с помощью обычных ассемблерных инструкций передачи данных, например, таких как MOV (см. § 3.1.1.2 “Интерфейс через память”). При работе через память скорость обмена платы с компьютером достигает 10 Мб/с. Базовый адрес доступа через память ниже 1 Мб находится в поле LowMemorySpaceBaseAddress структуры BOARD_INFO (см. § 2.1.5.1.1 “Структура BOARD_INFO”). Подробности организации низкоуровневого взаимодействия с платой можно найти в § 3.1 “Общий PCI-интерфейс работы с платами серии L7xx”. Если Вы желаете работать с платами через память ниже 1 Мб, Вам необходимо предотвратить употребление диапазона памяти выделенного для плат от использования каким то ни было администратором памяти (memory manager), таких как ЕММ386 или QEMM. Так при работе с ЕММ386 в файле config.sys строчка с ЕММ386.EXE должна содержать параметр X=mmmm-nnnn. Например, эта строчка может быть такой: DEVICE=C:\WINDOWS\EMM386.EXE X=C800-CA00. Диапазон памяти, выделяемый каждой плате серии L7xx, можно узнать с помощью утилиты \Utils\PARAMS\PARAMS.EXE (подробности см. приложение D). Если работа через память ниже 1 Мб Вам в принципе не нужна, то можно полностью запретить этот доступ, используя утилиту \Utils\CHIOMEM\CHIOMEM.EXE (подробности см. в приложении C).
К сожалению, во многих материнских платах (Iwill, Zida и т.д.) доступ к PCI платам через память ниже 1 Мб не работает вообще. Более того, возможно зависание компьютера при его загрузке в зависимости от взаимного расположения платы видеоадаптера и Вашей платы. Все платы серии L7xx ЗАО “Л-Кард" по умолчанию сконфигурированы в режим работы через порты ввода-вывода и через память выше 1 Мб (в 4 Гб адресном пространстве). Программно можно включить еще один тип доступа - через адресное пространство ниже 1 Мб для упрощения работы с платой под DOS. При этом возможны три варианта развития событий:
Компьютер грузится, и плата нормально работает в режиме доступа через память ниже 1 Мб (например, этот режим гарантированно работает на всех материнских платах ASUS).
Компьютер грузится, но плата не работает в режиме доступа через память ниже 1 Мб. Увы, Вам не повезло, желательно выключить режим доступа через нижнюю память или попробовать заменить системную плату.
Компьютер не грузится. Увы, Вам совсем не повезло, но не все еще потеряно. Следует поменять местами плату АЦП и видеокарту, после чего загрузка PC пройдет успешно, но плата через нижнюю память работать не будет. Желательно выключить режим доступа через нижнюю память или попробовать заменить системную плату.
Чтобы не быть голословными, ниже приведен ответ одного из импортных консультантов по PCI платам: "Some new PCs does not allow to use the memory below 1 MB. This space is reserved for some specific cards (like video card). If your application is a video card (for example), you should be able to run the PCI9050 in the lower memory < 1MB. Therefore, you can not configure the PCI 9050 using below 1MB memory address space". В заключение можно добавить, что подобных проблем при работе через верхнюю память и через порты ввода-вывода не возникает.
2.1.4.3.Особенности работы плат L7xx через память выше 1 Мб Платы серии L7xx дают пользователю возможность работы с ними как через порты ввода-вывода (традиционный подход), так и через память, которая расположена либо в диапазоне от 640 Кб до 1 Мб, либо где-нибудь выше 1 Мб. Под работой через память подразумевается работа с платой, когда все ее управляющие регистры “отображены” на память РС и доступ к ней возможен с помощью обычных ассемблерных инструкций передачи данных, таких как MOV (см. § 3.1.1.2 “Интерфейс через память”). При работе через память скорость обмена платы с компьютером достигает 10 Мб/с. Базовый адрес доступа через память выше 1 Мб находится в поле HighMemorySpaceBaseAddress структуры BOARD_INFO (см. § 2.1.5.1.1 “Структура BOARD_INFO”). На данный момент времени функции штатной библиотеки (под DOS) работают надлежащим образом с платами серии L7xx через память выше 1 Мб только если Ваша прикладная программа функционирует в “чистом” DOS. Это означает, что Вы должны находиться в реальном режиме работы центрального процессора PC, т.е. не использовать ни какой администратор памяти типа EMM386 или QEMM.
2.1.4.4.Особенности плат L-780M (Rev. С) Плата L-780M (Rev. С) представляет собой продукт основательной модернизации нашей старой серийной платы L-780 (Rev. B). С точки зрения конечного пользователя плата L-780M (Rev. С) унаследовала практически без изменений все основные функциональные характеристики старой платы. С другой стороны, модификация платы привнесла пользователю, кроме всего прочего, два весьма полезных улучшения, а именно:
Возможность организовывать работу потокового вывода на ЦАП, используя при этом дополнительно введённое прерывание от платы в РС;
Способность чисто программным образом управлять доступом выходных цифровых линий (т.е. перевод их ‘третье’ состояние и обратно). Для того чтобы иметь возможность воспользоваться указанным режимом, необходимо замкнуть перемычкой контакты 1–2 дополнительно появившегося на плате разъёма X5 (см. рисунок § 1.4.3.2. “Внешний вид платы L-780M (Rev. C)”). При этом непосредственно после подачи питания на плату выходные линии находятся в ‘третьем’ состоянии. Если же у этого разъёма перемычкой замкнуты контакты 2–3, то в части выходных цифровых линий плата получается полностью идентичной платам L-780 (Rev. A и B). В этом режиме после подачи питания на плату выходные линии находятся в неопределённом состоянии.
2.1.4.5.Общий подход к работе с API функциями Платы серии L7xx являются устройствами, предназначенными для работы с высоко производительной шиной PCI. Стандарт шины PCI предусматривает назначение каждой плате таких параметров как базовые адреса доступа (через порты ввода-вывода и/или память), номер прерываний и т.д. В основном, назначения подобного рода производит либо BIOS компьютера, либо WINDOWS. Поэтому на таких платах, как правило, не бывает конфигурационных перемычек и переключателей. Вся назначенная каждой PCI-плате информация хранится в так называемом конфигурационном пространстве PCI, прочитать которое можно с помощью надлежащих программных процедур (подробности можно найти, например, в “PCI Local Bus Specification. Revision 2.1”, § 3.7.4.1 “Configuration Mechanism #1”). В штатной библиотеке для этих целей предназначена функция READ_PCI_REG_PLX().
Другой особенностью плат данной серии является то, что на них установлен мощный цифровой сигнальный процессор (DSP – Digital Signal Processor). Для того, чтобы его “оживить” во внутреннюю память DSP надо записать (загрузить) фирменную управляющую программу, которая входит в комплект штатный поставки (файл с расширением .BIO), или свою собственную. Со стороны DSP весь обмен данными с PC осуществляется по так называемому каналу IDMA (Internal Direct Memory Access). Подробнее о работе канала IDMA можно прочитать, например, в оригинальной книге “ADSP-2100 Family User’s Manual (Includes ADSP-2171, ADSP-2181)”, Chapter 11 “DMA Ports”, § 11.3 “IDMA Port”, стр. 11-12, Analog Devices, Inc., Third Edition September 1995 или на сайте www.analog.com. Задачей DSP является управление всей периферией (АЦП, ЦАП, цифровые линии и т.д.) и обработка получаемый данных. Во внутренней памяти DSP расположены FIFO буфера АЦП и ЦАП, а также переменные LBIOS (см. приложение B). О низкоуровневом взаимодействии DSP с периферией см. Раздел 3 “НИЗКОУРОВНЕВОЕ ОПИСАНИЕ ПЛАТ СЕРИИ L7xx”
Перед началом работы со штатной библиотекой в Вашей программе необходимо сделать объявления следующих переменных:
extern int PLX_Board_Quantity; // объявленная в штатной библиотеке
// глобальная переменная, содержащая после выполнения
// функции INIT_ACCESS_TO_PLX() кол-во обнаруженных
// плат серии L7xx
struct BOARD_INFO bi[4]; // массив структур типа BOARD_INFO, описанных в
// штатной библиотеке, см. § 2.1.5.1.1 “Структура BOARD_INFO”
После того, как необходимые переменные объявлены, Вам следует просканировать все PCI пространство в поисках плат серии L7xx. Эту процедуру можно осуществить с помощью соответствующей API функции INIT_ACCESS_TO_PLX(struct BOARD_INFO *bi), которая аккуратно заполняет все поля массива структур типа BOARD_INFO для каждой обнаруженной платы, учитывая при этом служебную информацию, хранящуюся в пользовательском ППЗУ (см. § 2.1.2.3 “Формат пользовательского ППЗУ”). По окончании данной функции в переменной PLX_Board_Quantity будет содержаться количество обнаруженный плат серии L7xx.
Теперь, если обнаружена хотя бы одна плата, можно задать режим доступа функций штатной библиотеки к плате: через порты ввода-вывода, через память ниже 1 Мб или через память выше 1 Мб. Процедуру такого рода выполняет функция SET_ACCESS_MODE_PLX() (подробнее см. § 2.1.5.2.3 “Установка режима доступа к плате”).
Далее необходимо загрузить в сигнальный процессор платы управляющую программу (LBIOS). Для этого можно воспользоваться функцией LOAD_LBIOS_PLX(). В случае безошибочного выполнения данной функции, можно проверить работоспособность загруженного LBIOS с помощью функции PLATA_TEST_PLX(). Если и эта функция выполнена без ошибки, то это означает, что LBIOS успешно загружен и плата полностью готова к работе.
На следующем этапе следует настроить LBIOS на работу с тем типом DSP, который у Вас установлен на плате и прописан в ППЗУ (§ 2.1.2.3 “Формат пользовательского ППЗУ”). Функция SET_DSP_TYPE_PLX() как раз и предназначена для этой цели. Если функция не вернула ошибку, то это означает, что LBIOS благополучно настроился на нужный тип DSP.
В общем-то, ВСЕ! Теперь можно спокойно управлять всей доступной периферией на плате и самим DSP с помощью соответствующих API функций штатной библиотеки подпрограмм, т.е. задавать различные режимы работы АЦП (программный опрос FIFO буфера АЦП или по прерываниям, конфигурация FIFO буфера АЦП, синхронизация ввода данных с АЦП, частота оцифровки данных и т.д.) и ЦАП (конфигурация FIFO буфера ЦАП, частота выдачи данных на ЦАП и т.д.), обрабатывать входные и выходные цифровые линии, считывать и/или записывать необходимую информацию в/из пользовательского ППЗУ и т.д.
Перед выходом в DOS необходимо завершить работу с платами, вызвав функцию CLOSE_ACCESS_TO_PLX() (см. § 2.1.5.2.8 “Функция завершения работы с платам серии L7xx”).
В качестве примера приведем исходный текст программы для обнаружения и загрузки одной платы серии L7xx:
#include
#include
#include "plx_api.h" // заголовочный файл штатной библиотеки
extern int PLX_Board_Quantity; // кол-во обнаруженных плат серии L7xx
struct BOARD_INFO bi[3]; // массив из 3x структур BOARD_INFO
int main(void)
{
int AccessMode;
// просканируем все PCI пространство в поисках плат серии L7xx
INIT_ACCESS_TO_PLX(bi);
if(!PLX_Board_Quantity)
{
printf("Ни одной платы серии L7xx не обнаружено!\n");
CLOSE_ACCESS_TO_PLX(); return 1; //выйдем из программы с ошибкой
}
// разрешен ли доступ к первой из обнаруженных плат?
if(bi[0].BoardAccessMode == NO_ACCESS_MODE)
{
printf("Доступ к плате %s (серийный номер %s) ЗАПРЕЩЕН!!!\n",
bi[0].Board_Name, bi[0].BoardSerialNumber);
CLOSE_ACCESS_TO_PLX(); return 1; //выйдем из программы с ошибкой
}
else
{
// установим режим доступа к плате через память ниже 1 Мб
AccessMode = LOW_MEM_ACCESS;
SET_ACCESS_MODE_PLX(&bi[0], &AccessMode);
printf("Установлен режим доступа через %s для платы %s\
(серийный номер %s)!", AccessMode ? “память” : “порты”,
bi[0].Board_Name, bi[0].BoardSerialNumber);
}
// теперь попробуем загрузить LBIOS в первую из обнаруженных плат
if(!LOAD_LBIOS_PLX(&bi[0]))
{
printf("Не выполнена функция LOAD_LBIOS_PLX()!");
CLOSE_ACCESS_TO_PLX(); return 1; //выйдем из программы с ошибкой
}
if(!PLATA_TEST_PLX(&bi[0]))
{
printf("Не выполнена функция PLATA_TEST_PLX()!");
CLOSE_ACCESS_TO_PLX(); return 1; //выйдем из программы с ошибкой
}
// попробуем настроить LBIOS на нужный тип DSP
if(!SET_DSP_TYPE_PLX(&bi[0]))
{
printf("Не выполнена функция SET_DSP_TYPE_PLX ()!");
CLOSE_ACCESS_TO_PLX(); return 1; //выйдем из программы с ошибкой
}
printf("Плата %s (серийный номер %s) полностью готова к\
работе!", bi[0].Board_Name, bi[0].BoardSerialNumber);
// далее можно располагать функции для непосредственного
// управления платой!
. . . . . .
// завершим работу с платами
CLOSE_ACCESS_TO_PLX();
// выйдем в DOS
return 0;
}
2.1.4.6.Общая структура LBIOS На платах серии L7xx устанавливется так называемый цифровой сигнальный процессор (Digital Signal Processor – DSP) фирмы Analog Devices, Inc. ADSP-2184/2185/2186. Основное его назначение – это управление различного рода периферийными устройствами, установленными на плате, а также, возможно, обработка данных. Одно из главных преимуществ применения именно цифрового сигнального процессора заключается в том, что можно достаточно гибко менять в широких пределах алгоритмы его работы с периферийными устройствами чисто программным образом (достаточно лишь овладеть очень не сложным языком ассемблера DSP). Так в штатном драйвере LBIOS реализуются наиболее широко используемые алгоритмы работы с АЦП, ЦАП, входными/выходными ТТЛ линиями и т.д.
Для программиста нужно знать, что DSP обладает двумя независимыми типами памяти:
24 битная память программ (Program Memory – PM), в которой хранятся коды инструкций управляющей программы (драйвера LBIOS), а также, возможно, данные;
16 битная память данных (Data Memory – DM), в которой могут находится только данные.
Карты распределения памяти обоих типов для различных сигнальных процессоров, а также взаимное расположение составных частей LBIOS, подробно показаны в приложении B. Как видно из указанного приложения, LBIOS состоит из:
области в PM с исполняемыми кодами инструкций LBIOS;
области в DM с переменными LBIOS;
двумя областями под FIFO буфера АЦП и ЦАП.
Исполняемый код LBIOS написан с учетом возможности взаимодейтсвия драйвера с Вашей программой в РС по так называемому принципу команд. Это означает следующее:
в ячейку данных памяти DSP L_COMMAND (см. ниже) необходимо положить номер выполняемой команды с помощью функции PUT_DM_WORD_PLX();
инициировать в DSP прерывания IRQ2 (cм. § 3.1. “Общий PCI-интерфейс работы с платами серии L7xx”);
обработчик указанного прерывания,входящий в состав LBIOS, выполнит все необходимые для данной команды действия;
по окончании выполнения данной команды в ячейке L_COMMAND должно находиться число 0x0.
Адреса переменных в DM, задающих важные параметры функционирования LBIOS, а также их краткие толкования, приведены в Таблице 7.
В LBIOS организованно два циклических буфера: для приема данных с АЦП и для выдачи данных на ЦАП. Штатная библиотека работает с ними как с программно организованными FIFO буферами. Так, например, данные из буфера АЦП можно получать двумя способами: программно (cм. § 2.1.5.4.5. “Получение массива данных с АЦП”) и по прерываниям (cм. § 2.1.5.6. “Функции для работы с прерываниями”).
|