Перевод сделан по файлу
EZ-USB_FX2_TRM_version2-2.pdf. Это EZ-USB FX2 Technical Reference
Manual v2.2. ©CОПЫРИГХТ: Перевёл и положил на свою страничку http://www.dsioffe.narod.ru/ Дмитрий Иоффе. |
Универсальный программируемый интерфейс (General Programmable Interface, GPIF) - это внутреннее ведущее устройство (master) для конечной точки FIFO FX2. Он заменяет «склеивающую» логику, которая потребовалась бы в противном случае для построения интерфейса между FX2 и внешним миром.
Ядро GPIF - это программируемый цифровой автомат, который генерирует до шести управляющих и до девяти адресных выходных сигналов, и принимает шесть внешних и два внутренних сигнала готовности. Четыре определяемых пользователем дескриптора диаграмм (Waveform Descriptors) управляют цифровым автоматом. Обычно (но не обязательно) один из них описывает чтение из FIFO, другой - запись в FIFO, один - чтение одиночного байта или слова и один - запись одиночного байта или слова.
"Чтение" и "Запись" рассматриваются с точки зрения FX2. "Чтение" означает передачу данных из внешнего мира в FX2; "Запись" передаёт данные из FX2 во внешний мир.
Встроенное ПО FX2 может назначить временные диаграммы чтения и записи FIFO для любого из четырёх FIFO, и GPIF будет генерировать соответствующие сигналы стробирования и квитирования, чтобы обеспечить интерфейс с внешним миром при передаче данных в и из FIFO.
При управлении извне (см. Главу 9 "Ведомые FIFO") шина данных между FIFO и внешним миром может быть 8- или 16-разрядной.
GPIF не ограничивается простым интерфейсом с квитированием между FX2 и внешними СБИС или микропроцессорами. Он может непосредственно реализовать такие протоколы, как ATAPI (PIO и UDMA), IEEE1284 (параллельный порт EPP), Utopia и т.п. Например, FX2 может работать как однокристальный интерфейс между USB и жёстким диском IDE или картой памяти CompactFlash™.
В этой главе приводится обзор GPIF, обсуждаются внешние соединения и разъясняется работа механизма GPIF. На рисунке 10-1 показана блок-схема, иллюстрирующая место GPIF в системе FX2.
Временные диаграммы GPIF обычно создаются при помощи утилиты GPIFTool от фирмы Cypress. Это Windows™-приложение, распространяемое в составе Cypress EZ-USB FX2 Development Kit. Несмотря на то, что в этой главе достаточно детально описывается структура дескрипторов временных диаграмм (Waveform Descriptors), знание этой структуры обычно не обязательно. GPIFTool просто скрывает сложность Waveform Descriptors. Это не мешает программисту управлять GPIF любым способом.
Рисунок 10-1. Место GPIF в системе FX2
На рисунке 10-2 приведён пример простой транзакции GPIF. Для этой транзакции GPIF генерирует адрес (GPIFADR[8:0]), выставляет код на шину данных FIFO (FD[15:0]), затем ждёт низкого уровня внешнего квитирующего сигнала (RDY0), после чего устанавливает низкий уровень на выходе CTL0. Когда на RDY0 возвращается высокий уровень, GPIF устанавливает высокий уровень на CTL0 и затем переводит шину данных в третье состояние.
Рисунок 10-2. Пример временной диаграммы GPIF
GPIF позволяет непосредственно подключать EZ-USB FX2 к внешним периферийным устройствам, таким, как ASIC, DSP или другая цифровая логика, которая использует 8- или 16=разрядный параллельный интерфейс.
GPIF предоставляет внешние выводы, которые могут работать как выходы (CTL[5:0]), входы (RDY[5:0]), шина данных (FD[15:0]) и адресные линии (GPIFADR[8:0]).
Дескрипторы временной диаграммы во внутреннем ОЗУ описывают поведение каждого из сигналов GPIF. Встроенное ПО FX2 загружает эти дескрипторы в регистры GPIF во время инициализации, и они затем используются через исполнение кода для выполнения транзакций через интерфейс GPIF.
На рисунке 10-3 показана блок-схема типичного интерфейса между EZ-USB FX2 и периферийным устройством.
Рисунок 10-3. Интерфейс между EZ-USB FX2 и периферией
В следующем разделе подробнее рассматриваются доступные возможности и последовательность действий при разработке проекта GPIF. Сюда входят определение внешних подключений GPIF и установка внутренних регистров, которую встроенное ПО FX2 должно обеспечить для выполнения передачи данных через интерфейс.
В таблице 10-1 перечислены регистры, связанные с аппаратной частью GPIF. Детальное описание каждого регистра можно найти в главе 15 "Регистры".
Таблица 10-1. Регистры, связанные с аппаратной частью GPIF
Обратите внимание: "x" в именах этих регистров может означать 2, 4, 6 или 8. Конечные точки 0 и 1 не связаны с GPIF.
GPIF предоставляет множество входных и выходных сигналов, через которые внешние периферийные устройства могут быть подключены к FX2 без использования "склеивающей" логики.
Сигналы интерфейса GPIF показаны в таблице 10-2.
Вывод | Вход/Выход | Описание |
---|---|---|
CTL[5:0] | Выходы/Высокий импеданс | Программируемые управляющие выходы |
RDY[5:0] | Входы | Опрашиваемые входы готовности |
FD[15:0] | Входы/Выходы/Высокий импеданс | Двунаправленная шина данных FIFO |
GPIFADR[8:0] | Выходы/Высокий импеданс | Адресные выходы |
IFCLK | Вход/Выход | Тактирование интерфейса |
GSTATE[2:0] | Выходы/Высокий импеданс | Номер текущего состояния GPIF (для отладки) |
Управляющие выходы (CTL[5:0]) обычно используются как стробы (разрешающие линии), линии чтения/записи и т.д.
Входы готовности (RDY[5:0]) опрашиваются GPIF и могут заставлять тразакцию ждать (вставляют состояния ожидания), продолжаться или повторяться, пока они находятся в определённом состоянии.
Шина данных GPIF состоит из выводов FD[15:0].
Адресные линии GPIF (GPIFADR[8:0]) могут при передаче данных генерировать инкрементируемый адрес. Если понадобятся адресные линии для старших разрядов, можно использовать не GPIF сигналы ввода-вывода (сигналы ввода-вывода общего назначения).
Тактовый сигнал интерфейса (Interface Clock, IFCLK) может быть сконфигурирован как входной (по умолчанию) или как выходной для синхронизации внешней логики.
Выходы GSTATE[2:0] показывают номер текущего состояния GPIF. Это обычно используется для отладки временных диаграмм GPIF.
FX2 выходит из состояния сброса с линиями ввода-вывода в режиме "Порты" ("Ports"), не в режиме "GPIF Master". Чтобы сконфигурировать выводы для режима GPIF, надо установить биты IFCFG[1:0] в регистре IFCONFIG в 10 (подробнее см. таблицу 13-10, "Выбор функций линий ввода-вывода в IFCFG").
В корпусах со 100 и 128 выводами наружу выведены все шесть управляющих выходов, CTL[5:0]. В корпусе с 56 выводами выведены только три из этих сигналов, CTL[2:0]. Скорость переключений на этих выводах может быть запрограммирована вплоть до одного переключения за период тактовой частоты (каждые 20,8 нс, если IFCLK работает от 48 МГц).
По умолчанию на этих линиях высокий уровень.
Управляющие выходы GPIF CTL[5:0] могут работать в следующих режимах:
Если CTL[3:0] сконфигурированы как тристабильные, то CTL[5:4] недоступны.
TRICTL (GPIFCTLCFG.7) | GPIFCTLCFG[6:0] | CTL[3:0] | CTL[5:4] |
---|---|---|---|
0 | 0 | КМОП, не тристабильные | КМОП, не тристабильные |
0 | 1 | Открытый сток | Открытый сток |
1 | X | КМОП, тристабильные | Недоступны |
В корпусах со 100 и 128 выводами наружу выведены все шесть входов готовности, RDY[5:0]. В корпусе с 56 выводами выведены только два из этих сигналов, RDY[1:0].
Входы готовности могут опрашиваться синхронно или асинхронно. Когда GPIF находится в асинхронном режиме (SAS=0), входы RDY неизбежно немного запаздывают (примерно на 24 нс при 48 МГц IFCLK). Другими словами, когда GPIF "смотрит" на входы RDY, он видит их состояние, которое было 24 нс назад.
В GPIF имеется девять адресных линий, GPIFADR[8:0]. Если адресные линии сконфигурированы как выходы, запись в регистры GPIFADRH:L управляет этими выходами непосредственно. Механизм GPIF может также инкрементировать их код под управлением дескрипторов временных диаграмм. Адресные линии GPIF можно перевести в третье состояние, сбросив ассоциированные биты PORTxCFG и OEx (см. пункт 13.3.3 "Альтернативные функции порта C" и пункт 13.3.4 "Альтернативные функции порта E").
Три выходных линии GPIF GSTATE[2:0] доступны при альтернативной конфигурации PORTE[2:0]. По умолчанию это входы общего назначения. Установка GSTATE (IFCONFIG2) в 1 включит альтернативную конфигурацию и перекроет установку битов PORTECFG[2:0].
Выводы GSTATE[2:0] содержат номер текущего состояния GPIF. Это свойство обычно используется только для отладки временных диаграмм GPIF.
Когда FX2 сконфигурирован для ведущего режима (Master mode) GPIF, PORTB всегда конфигурируется как FD[7:0].
Если любой из битов WORDWIDE установлен в 1, то PORTD автоматически конфигурируется как FD[15:8]. Если все биты WORDWIDE сброшены, PORTD доступен для ввода-вывода общего назначения.
Данные пересылаются через USB пакетами 8-битных байтов, а не 16-битных слов. Когда ширина шины данных FIFO 16 битов, первый байт каждой пары, проходящей через USB, передаётся через FD[7:0], а второй байт - через FD[15:8].
GPIF может тактироваться как от внутреннего, так и от внешнего источника. Внутренний тактовый генератор FX2 может быть сконфигурирован для работы на частоте 30 или 48 МГц, и он может быть опционально подан на вывод IFCLK. Если FX2 сконфигурирован для использования внешней тактовой частоты, на вывод IFCLK можно подавать от 5 МГц до 40 МГц. При включении питания FX2 по умолчанию использует внутреннюю тактовую частоту 48 МГц нормальной полярности, выход IFCLK отключён. См. рис. 10-4.
IFCONFIG.7 выбирает внутренний или внешний источник тактирования: 0=внешний, 1=внутренний.
IFCONFIG.6 определяет внутреннюю частоту тактирования: 0=30МГц, 1=48МГц. Если IFCONFIG.7=0, то этот бит ни на что не влияет.
IFCONFIG.5 разрешает передачу сигнала внутреннего тактового генератора на выход: 0 запрещает, 1 разрешает. Если IFCONFIG.7=0, то этот бит ни на что не влияет.
IFCONFIG.4 инвертирует полярность тактовых импульсов интерфейса (внутренних или внешних): 0 - нормальная полярность, 1 - инвертирование. Инверсия IFCLK может использоваться для упрощения интерфейса с некоторыми внешними схемами. Например, на рисунке 10-5 показано использование инверсии IFCLK для получения достаточного времени установления при чтении периферийных сигналов.
Когда IFCLK сконфигурирован как вход, минимальная внешняя частота, которая может быть на него подана, равна 5 МГц.
Рисунок 10-4. Конфигурирование IFCLK
Рисунок 10-5. Получение нужного времени установления инвертированием выхода IFCLK
Первый шаг при создании интерфейса между GPIF FX2 и внешней периферией - это создание аппаратных связей.
В следующем примере показаны подключения, которые потребуются для организации стандартного интерфейса с EPROM 27C256.
Шаг | Результат | Сделанные соединения |
---|---|---|
1. Выбираем настройки IFCLK. | Внутренний IFCLK, 48 МГц, асинхронный GPIF | Нет подключений |
2. Определяем ширину шины даннх FIFO. | 8 битов от EPROM | От FD[7:0] к D[7:0]. Встроенное ПО записывает WORDWIDE=0. |
3. Назначаем сигналы CTLx. | nCS и nOE для входов EPROM. | CTL0 на nCS, CTL1 на nOE |
4. Назначаем сигналы RDYn. | У EPROM 27C256 нет выходных сигналов чтения/ожидания | Нет подключений |
5. Определяем подключение адресной шины. | 16 битов адреса | GPIFADR[8:0] на A[8:0] и другие линии ввода-вывода на A[15:9]. |
Для других, более сложных, интерфейсов процесс остаётся тем же самым.
Каждый дескриптор временных диаграмм GPIF может определять до семи состояний. В каждом состоянии GPIF может быть запрограммирован так, чтобы:
Кроме того, в каждом состоянии могут опрашиваться любые два из следующих источников:
Состояния, в которых происходит опрос и переход, называются точками решения (Decision Points, DP). Остальные состояния называются точками не-решения (Non-Decision Points, NDP).
Рисунок 10-6. Общее представление о цифровом автомате GPIF
Два блока регистров, управляющих цифровым автоматом GPIF:
До тех пор, пока встроенное ПО не загрузит регистры конфигурации и регистры временных диаграмм, GPIF не может начать передачу данных.
Доступ к регистрам временных диаграмм разрешается только тогда, когда FX2 находится в режиме GPIF (т.е. IFCFG[1:0] = 10). Запись в регистры временных диаграмм возможна только тогда, когда механизм GPIF остановлен (т.е. DONE = 1).
Если требуется динамическая реконфигурация дескрипторов временных диаграмм, её можно выполнить путём перезаписи только тех байтов, которые требуют изменения. Необязательно перезагружать все дескрипторы временных диаграмм, чтобы изменить только несколько байтов.
"Программой" для GPIF служат дескрипторы временных диаграмм, которые записываются в регистры временных диаграмм встроенным ПО FX2.
FX2 может хранить до четырёх дескрипторов временных диаграмм, каждый из которых может быть использован для одного из четырёх типов передачи: однократная запись, однократное чтение, запись в FIFO и чтение из FIFO. По умолчанию для каждого типа передачи назначается один дескриптор, но эту конфигурацию сохранять необязательно. Например, все четыре дескриптора могут быть сконфигурированы для записи в FIFO (см. описание регистра GPIFWFSELECT в главе 15 "Регистры").
Каждый дескриптор временных диаграмм содержит до семи 32-разрядных Инструкций состояния (State Instructions), которые программируют коды точек перехода для сигналов интерфейса GPIF. Между инструкциями состояния и состояниями цифрового автомата GPIF существует однозначное соответствие. Среди прочего, каждая инструкция состояния определяет состояние выходов CTLx, состояние FD[15:0], использование входов RDYn и поведение GPIFADR[8:0].
Переходы из одного состояния GPIF в другое всегда происходят по нарастающему фронту IFCLK, но GPIF может сохранять одно и то же состояние в течение многих циклов IFCLK.
Временная диаграмма содержит до семи программируемых состояний, от S0 до S6, и одно специальное состояние ожидания, S7. Временная диаграмма заканчивается, когда программа GPIF переходит в состояние ожидания.
Для завершения транзакции GPIF программа GPIF должна перейти к состоянию ожидания, независимо от состояния, в котором эта программа находится в настоящий момент. Например, временная диаграмма GPIF может быть задана программой, которая содержит только два программируемых состояния, S0 и S1. Чтобы завершиться, программа должна из состояния S1 (или S0) перейти в S7.
Состояние сигналов GPIF во время состояния ожидания определяется содержимым регистров GPIFIDLECS и GPIFIDLECTL.
Когда временная диаграмма уже началась, другая временная диаграмма не может стартовать, пока первая не закончится. Об окончании временной диаграммы сообщает бит DONE (GPIFIDLECS.7 или GPIFTRIG.7) или, опционально, прерывание GPIFDONE.
Важно: при возникновении исключительной ситуации (запись в регистр GPIFABORT для принудительного завершения временной диаграммы) не допускается запись в какие-либо регистры, связанные с GPIF (включая регистры временных диаграмм), пока GPIF занят. Это может привести к непредсказуемому поведению и повреждению данных.
В состоянии ожидания выходы шины данных GPIF могут быть активны или находиться в третьем состоянии, в зависимости от состояния бита IDLEDRV (GPIFIDLECS.0):
В состоянии ожидания состояние выходов CTL[5:0] зависит от следующих битов:
Комбинация этих битов определяет состояние CTL[5:0] следующим образом:
Эти зависимости показаны в таблице 10.5.
Таблица 10-5. Управляющие выходы (CTLn) во время
состояния ожидания
Каждая временная диаграмма состоит из некоторого числа состояний, каждое из которых определяется 32-разрядной инструкцией состояния. Каждое состояние может принадлежать к одному из двух основных типов: точка не-решения (Non-Decision Point, NDP) или точка решения (Decision Point, DP).
Для временных диаграмм "записи" шина данных в каждом состоянии может быть активна или находиться в третьем состоянии. Для временных диаграмм "чтения" шина данных в каждом состоянии может опрашиваться или не опрашиваться.
Состояние управляющих выходов (CTLx) в точках не-решения определяется инструкциями GPIF. На выходе может быть 0, 1 или третье состояние. Длительность состояний NDP программируется и задаётся в циклах IFCLK.
Рисунок 10-7 иллюстрирует базовую концепцию состояний NDP. Показана временная диаграмма записи, и для упрощения все состояния имеют одинаковую длительность. На рисунке показан только один управляющий выход из шести, CTL0.
Рисунок 10-7. Базовая концепция состояний NDP
Рассмотрим рисунок 10-7:
В состоянии 0:Так как все состояния в этом примере закодированы как NDP, GPIF автоматически переходит из состояния S6 в состояние ожидания S7. В этом состоянии GPIF ждёт, пока встроенное ПО запустит следующую временную диаграмму.
Состояния 2 и 3 в этом примере идентичны, как и состояния 5 и 6. В реальном приложении можно делать иначе: необязательно дублировать состояния, чтобы "растягивать" их, можно назначать длительность каждого состояния не-решения в циклах IFCLK. Если для данной временной диаграммы определено меньше семи состояний, состояние ожидания автоматически наступает после последнего запрограммированного состояния. Инструкция для этого последнего запрограммированного состояния должна в явном виде содержать переход в состояние ожидания.
Любое состояние может быть сделано точкой решения (Decision Point, DP). DP позволяет механизму GPIF опрашивать два сигнала (это может быть один и тот же сигнал), при необходимости выполнять булевскую операцию над полученными значениями, затем переходить в другое состояние (или циклически возвращаться в то же самое, сохраняя тем самым текущее состояние) в зависимости от результата.
Если инструкция состояния включает задачу управления (продвижение указателя FIFO, инкремент адреса GPIFADR и т.д.), то эта задача всегда выполняется один раз при входе в состояние, независимо от того, является ли это состояние DP или NDP. Если это состояние - DP, циклически возвращающееся в себя, оно может быть запрограммировано на повторное выполнение задачи управления на каждом цикле.
В точке решения GPIF может выполнять простые задачи (например, ожидать, пока на линии RDY появится низкий уровень, чтобы перейти в следующее состояние). Состояние точки решения может также выполнять более сложные задачи, переходя в одно состояние, если в результате опроса сигналов получается логическая 1, и в другое, если получается 0.
Два смгнала, которые опрашиваются в каждой инструкции состояния, могут быть выбраны из следующиего списка:
Инструкция состояние также определяет логическую функцию (И, ИЛИ или Исключающее ИЛИ), которая будет обрабатывать два выбранных сигнала. Если надо работать только с одним сигналом, то обычно задают этот сигнал дважды и применяют логическую функцию И.
Инструкция состояния также задаёт, в какое состояние переходить, если результат логического выражения равен 0, а в какое - если 1.
Ниже приведён пример временной диаграммы, созданной с использованием одной точки решения (состояние 1). Состояния не-решения используются для паузы во временной диаграмме.
Рисунок 10-8. Одна точка решения: состояния ожидания вставляются до тех пор, пока на RDY0 не появится низкий уровень
Рисунок 10-9. Одна точка решения: состояния ожидания не вставляются: в точке решения S1 на RDY0 уже низкий уровень
На рисунках 10-8 и 10-9 одна точка решения, определённая как Состояние 1. В этом примере входной сигнал готовности поступает с линии RDY, и инструкция состояния для S1 сконфигурирована так, чтобы переходить в состояние 2, если на RDY0 логический 0, и в состояние 1, если логическая 1 (то есть бесконечный цикл).
На рисунке 10-8 GPIF остаётся в S1, пока на RDY0 не появится низкий уровень, затем переходит в S2. Рисунок 10-9 показывает поведение GPIF, когда при входе в состояние S1 на RDY0 уже низкий уровень: GPIF переходит в S2.
Несмотря на то, что на рисунке 10-8 показано, что GPIF переходит непосредственно из состояния 0 в состояние 2, это не совсем так. Даже если перед тем, как GPIF входит в состояние 1, на RDY уже низкий уровень, GPIF проводит один такт IFCLK в состоянии 1.
В простых примерах DP, показанных ранее в этой главе, задача управления (например, вывод слова на FD[15:0] и инкремент GPIFADR[8:0] выполняется только один раз в начале состояния DP, а затем GPIF ждёт, опрашивая вход RDYx, пока он не "скажет" GPIF перейти в следующее состояние.
GPIF способен также повторно выполнять задачу управления при каждом опросе RDYx. Это свойство может быть использовано для пакетной передачи большого количества данных без прохождения через состояние ожидания.
Рисунок 10-10. Повторное выполнение задачи в состоянии DP
Рисунок 10-11. Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-10
Рисунок 10-12. Состояние DP, в котором НЕ происходит повторное выполнение задачи
Рисунок 10-13. Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-12
Характеристики каждого состояния определяются четырьмя байтами инструкции состояния. Эти четыре байта называются LENGTH / BRANCH, OPCODE, LOGIC FUNCTION и OUTPUT (ДЛИНА / ВЕТВЛЕНИЕ, КОД ОПЕРАЦИИ, ЛОГИЧЕСКАЯ ФУНКЦИЯ и ВЫХОД).
Обратите внимание, что инструкции состояния по-разному интерпретируются для точек решения (DP=1) и точек не-решения (DP=0).
Инструкция состояния для точки не-решения (DP=0)
Инструкция состояния для точки решения (DP=1)
Регистр LENGTH / BRANCH . Этот регистр интерпретируется в зависимости от бита DP:
Регистр OPCODE . Этот регистр определяет несколько характеристик состояния.
Бит SGL: Не влияет на временные диаграммы однократного чтения и
однократной записи. Для временной диаграммы FIFO он задаёт, должна ли
произойти однократная передача данных (из/в регистры SGLDATAH:L или
UDMA_CRCH:L), даже если выполняется запись FIFO или чтение из FIFO. См.
также "NEXT/SGLCRC" ниже.
1 = использование SGLDATAH:L или UDMA_CRCH:L.
0 = использование FIFO
Бит GINT: определяет, надо ли генерировать прерывание GPIFWF во
время этого состояния.
1 = генерировать прерывание GPIFWF (на INT4) при
переходе в это состояние.
0 = не генерировать прерывание.
Бит INCAD: определяет, надо ли инкрементировать адрес GPIF на
линиях GPIFADR[8:0].
1 = инкрементировать адресную шину в начале этого
состояния.
0 = не инкрементировать сигналы GPIFADR[8:0].
Бит NEXT/SGLCRC:
Если SGL = 0, определяет, надо ли продвигать FIFO на старте этого
состояния:
1 = переслать следующие данные в OUT FIFO наверх.
0 = не продвигать FIFO.
Бит NEXT не влияет, когда временная диаграмма работает
на IN FIFO.
Если SGL = 1, то задаёт, должны данные передаваться в/из SGLDATAH:L или
UDMA_CRCH:L. См. также "Бит SGL" выше.
1 = использовать UDMA_CRCH:L.
0 = использовать SGLDATAH:L.
Бит DATA задаёт режим работы шины данных FIFO.
Во время записи:
1 = на шине выходные данные.
0 = шина в третьем состоянии.
Во время чтения:
1 = опрос шины данных и запись данных.
0 = нет опроса данных.
Бит DP: указывает тип состояния: DP или NDP.
1 = точка решения
0 = точка не-решения
Регистр LOGIC FUNCTION. Этот регистр используется только для инструкций состояния DP. Он задаёт входы (TERMA и TERMB) и логическую функцию (LFUNC) для этих входов. Результат логической функции определяет состояние, в которое перйдёт GPIF (см.также выше "Регистр LENGTH / BRANCH").
Биты TERMA и TERMB:
= 000: RDY0
= 001: RDY1
= 010: RDY2
= 011: RDY3
= 100: RDY4
= 101: RDY5 (или завершение счёта транзакций, если GPIFREADYCFG.5 = 1)
= 110: флаг FIFO (PF, EF, or FF), предварительно выбранный через EPxGPIFFLGSEL
= 111: INTRDY (Бит 7 регистра GPIFREADYCFG )
Биты LFUNC:
= 00: A AND B
= 01: A OR B
= 10: A XOR B
= 11: A AND B
Биты TERMA и TERMB опрашиваются по каждому положительному перепаду IFCLK. Они обрабатываются логической функцией, и затем по следующему положительному перепаду происходит ветвление.
Этот регистр имеет значение только для DP инструкций. Когда бит DP в регистре OPCODE сброшен, содержимое этого регистра игнорируется.
Регистр OUTPUT: этот регистр управляет состоянием шести
управляющих выходов (CTL5:0) в течение всего состояния, задаваемого этой
инструкцией.
Бит OEn: если TRICTL = 1, управляет установкой
третьего состояния на соответствующем выходе CTLx:
1 = активный CTLx
0 = третье состояние CTLx
Бит CTLn: определяет уровень на выходе CTLx в
течение всего состояния.
1 = высокий уровень
Если бит CTLx в регистре GPIFCTLCFG установлен, выходной драйвер будет с
открытым стоком.
Если этот бит сброшен, то драйвер будет формировать КМОП уровни.
0 = низкий уровень
Можно определить до четырёх различных временных диаграмм. Каждый дескриптор содержит до семи инструкций состояния, которые загружаются в регистры временных диаграмм так, как описано в этом разделе.
Таблица 10-6. Адреса дескрипторов временных диаграммВнутри каждого дескриптора временной диаграммы инструкции состояния упакованы так, как описано в таблице 10-7 "Структура дескриптора временной диаграммы 0". Дескриптор временной диаграммы 0 показан для примера. Другие дескрипторы построены так же, но имеют бОльшие адреса XDATA.
Таблица 10-7. Структура дескриптора временной диаграммы 0
В этих именах регистров "x" может означать 2, 4, 6 или 8; конечные точки 0 и 1 не связаны с ведомыми FIFO.
Утилита GPIFTool, распространяемая с Cypress EZ-USB FX2 Development Kit, генерирует C-код, который может быть скомпонован с основным исходным кодом приложения. Выходной код GPIFTool включает следующие основные структуры и функции GPIF:
TD_Init(): ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform data // TODO: configure other endpoints, etc. here // TODO: arm OUT buffer(s) here // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring // SYNCDELAY; //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) // SYNCDELAY; //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... void GpifInit( void ) { BYTE i; // Registers which require a synchronization delay, see section 15.14 // FIFORESET FIFOPINPOLAR // INPKTEND OUTPKTEND // EPxBCH:L REVCTL // GPIFTCB3 GPIFTCB2 // GPIFTCB1 GPIFTCB0 // EPxFIFOPFH:L EPxAUTOINLENH:L // EPxFIFOCFG EPxGPIFFLGSEL // PINFLAGSxx EPxFIFOIRQ // EPxFIFOIE GPIFIRQ // GPIFIE GPIFADRH:L // UDMACRCH:L EPxGPIFTRIG // GPIFTRIG // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... // ...these have been replaced by GPIFTC[B3:B0] registers // 8051 doesn't have access to waveform memories 'til // the part is in GPIF mode. IFCONFIG = 0xCE; // IFCLKSRC=1 , FIFOs executes on internal clk source // xMHz=1 , 48MHz internal clk rate // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk // ASYNC=1 , master samples asynchronous // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF // IFCFG[1:0]=10, FX2 in GPIF master mode GPIFABORT = 0xFF; // abort any waveforms pending GPIFREADYCFG = InitData[ 0 ]; GPIFCTLCFG = InitData[ 1 ]; GPIFIDLECS = InitData[ 2 ]; GPIFIDLECTL = InitData[ 3 ]; GPIFWFSELECT = InitData[ 5 ]; GPIFREADYSTAT = InitData[ 6 ]; // use dual autopointer feature... AUTOPTRSETUP = 0x07; // inc both pointers, // ...warning: this introduces pdata hole(s) // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) // source APTR1H = MSB( &WaveData ); APTR1L = LSB( &WaveData ); // destination AUTOPTRH2 = 0xE4; AUTOPTRL2 = 0x00; // transfer for ( i = 0x00; i < 128; i++ ) { EXTAUTODAT2 = EXTAUTODAT1; } // Configure GPIF Address pins, output initial value, PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] OEC = 0xFF; // and as outputs PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] OEE |= 0x80; // and as output // ...OR... tri-state GPIFADR[8:0] pins // PORTCCFG = 0x00; // [7:0] as port I/O // OEC = 0x00; // and as inputs // PORTECFG &= 0x7F; // [8] as port I/O // OEE &= 0x7F; // and as input // GPIF address pins update when GPIFADRH/L written SYNCDELAY; // GPIFADRH = 0x00; // bits[7:1] always 0 SYNCDELAY; // GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 } #ifdef TESTING_GPIF // TODO: You may add additional code below. void OtherInit( void ) { // interface initialization // ...see TD_Init( ); } // Set Address GPIFADR[8:0] to PERIPHERAL void Peripheral_SetAddress( WORD gaddr ) { SYNCDELAY; // GPIFADRH = gaddr >> 8; SYNCDELAY; // GPIFADRL = ( BYTE )gaddr; // setup GPIF address } // Set EP2GPIF Transaction Count void Peripheral_SetEP2GPIFTC( WORD xfrcnt ) { SYNCDELAY; // EP2GPIFTCH = xfrcnt >> 8; // setup transaction count SYNCDELAY; // EP2GPIFTCL = ( BYTE )xfrcnt; } // Set EP4GPIF Transaction Count void Peripheral_SetEP4GPIFTC( WORD xfrcnt ) { SYNCDELAY; // EP4GPIFTCH = xfrcnt >> 8; // setup transaction count SYNCDELAY; // EP4GPIFTCL = ( BYTE )xfrcnt; } // Set EP6GPIF Transaction Count void Peripheral_SetEP6GPIFTC( WORD xfrcnt ) { SYNCDELAY; // EP6GPIFTCH = xfrcnt >> 8; // setup transaction count SYNCDELAY; // EP6GPIFTCL = ( BYTE )xfrcnt; } // Set EP8GPIF Transaction Count void Peripheral_SetEP8GPIFTC( WORD xfrcnt ) { SYNCDELAY; // EP8GPIFTCH = xfrcnt >> 8; // setup transaction count SYNCDELAY; // EP8GPIFTCL = ( BYTE )xfrcnt; } #define GPIF_FLGSELPF 0 #define GPIF_FLGSELEF 1 #define GPIF_FLGSELFF 2 // Set EP2GPIF Decision Point FIFO Flag Select (PF, EF, FF) void SetEP2GPIFFLGSEL( WORD DP_FIFOFlag ) { EP2GPIFFLGSEL = DP_FIFOFlag; } // Set EP4GPIF Decision Point FIFO Flag Select (PF, EF, FF) void SetEP4GPIFFLGSEL( WORD DP_FIFOFlag ) { EP4GPIFFLGSEL = DP_FIFOFlag; } // Set EP6GPIF Decision Point FIFO Flag Select (PF, EF, FF) void SetEP6GPIFFLGSEL( WORD DP_FIFOFlag ) { EP6GPIFFLGSEL = DP_FIFOFlag; } // Set EP8GPIF Decision Point FIFO Flag Select (PF, EF, FF) void SetEP8GPIFFLGSEL( WORD DP_FIFOFlag ) { EP8GPIFFLGSEL = DP_FIFOFlag; } // Set EP2GPIF Programmable Flag STOP, overrides Transaction Count void SetEP2GPIFPFSTOP( void ) { EP2GPIFPFSTOP = 0x01; } // Set EP4GPIF Programmable Flag STOP, overrides Transaction Count void SetEP4GPIFPFSTOP( void ) { EP4GPIFPFSTOP = 0x01; } // Set EP6GPIF Programmable Flag STOP, overrides Transaction Count void SetEP6GPIFPFSTOP( void ) { EP6GPIFPFSTOP = 0x01; } // Set EP8GPIF Programmable Flag STOP, overrides Transaction Count void SetEP8GPIFPFSTOP( void ) { EP8GPIFPFSTOP = 0x01; } // write single byte to PERIPHERAL, using GPIF void Peripheral_SingleByteWrite( BYTE gdata ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } XGPIFSGLDATLX = gdata; // trigger GPIF // ...single byte write transaction } // write single word to PERIPHERAL, using GPIF void Peripheral_SingleWordWrite( WORD gdata ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space XGPIFSGLDATH = gdata >> 8; XGPIFSGLDATLX = gdata; // trigger GPIF // ...single word write transaction } // read single byte from PERIPHERAL, using GPIF void Peripheral_SingleByteRead( BYTE xdata *gdata ) { static BYTE g_data = 0x00; while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, dummy read g_data = XGPIFSGLDATLX; // trigger GPIF // ...single byte read transaction while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, *gdata = XGPIFSGLDATLNOX; // ...GPIF reads byte from PERIPHERAL } // read single word from PERIPHERAL, using GPIF void Peripheral_SingleWordRead( WORD xdata *gdata ) { BYTE g_data = 0x00; while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, dummy read g_data = XGPIFSGLDATLX; // trigger GPIF // ...single word read transaction while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, GPIF reads word from PERIPHERAL *gdata = ( ( WORD )XGPIFSGLDATH << 8 ) | ( WORD )XGPIFSGLDATLNOX; } #define GPIFTRIGWR 0 #define GPIFTRIGRD 4 #define GPIF_EP2 0 #define GPIF_EP4 1 #define GPIF_EP6 2 #define GPIF_EP8 3 // write byte(s)/word(s) to PERIPHERAL, using GPIF and EPxFIFO // if EPx WORDWIDE=0 then write byte(s) // if EPx WORDWIDE=1 then write word(s) void Peripheral_FIFOWrite( BYTE FIFO_EpNum ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // trigger FIFO write transaction(s), using SFR GPIFTRIG = FIFO_EpNum; // R/W=0, EP[1:0]=FIFO_EpNum for EPx write(s) } // read byte(s)/word(s) from PERIPHERAL, using GPIF and EPxFIFO // if EPx WORDWIDE=0 then read byte(s) // if EPx WORDWIDE=1 then read word(s) void Peripheral_FIFORead( BYTE FIFO_EpNum ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 GPIF Done bit { ; } // trigger FIFO read transaction(s), using SFR GPIFTRIG = GPIFTRIGRD | FIFO_EpNum; // R/W=1, EP[1:0]=FIFO_EpNum for EPx read(s) }
Рисунок 10-14. Встроенное ПО запускает временную диаграмму однократного чтения, WORDWIDE = 0
Рисунок 10-15. Временная диаграмма однократного чтения
Рисунок 10-16. Настройка GPIGTool для временной диаграммы на рисунке 10-15
Чтобы выполнить транзакцию однократного чтения, необходимо:
Следующий фрагмент программы на C (рисунки 10-17 и 10-18) иллюстрирует, как выполнить транзакцию однократного чтения в 8-разрядном режиме (WORDWIDE = 0):
#define PERIPHCS 0x00AB #define AOKAY 0x80 #define BURSTMODE 0x0000 #define TRISTATE 0xFFFF #define EVER ;; // prototypes void GpifInit( void ); // Set Address GPIFADR[8:0] to PERIPHERAL void Peripheral_SetAddress( WORD gaddr ) { if( gaddr < 512 ) { // drive GPIF address bus w/gaddr GPIFADRH = gaddr >> 8; SYNCDELAY; GPIFADRL = ( BYTE )gaddr; // setup GPIF address } else { // tristate GPIFADR[8:0] pins PORTCCFG = 0x00; // [7:0] as port I/O OEC = 0x00; // and as inputs PORTECFG &= 0x7F; // [8] as port I/O OEE &= 0x7F; // and as input } } // read single byte from PERIPHERAL, using GPIF void Peripheral_SingleByteRead( BYTE xdata *gdata ) { static BYTE g_data = 0x00; while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, dummy read g_data = XGPIFSGLDATLX; // to trigger GPIF single byte read transaction while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // using register(s) in XDATA space, GPIF read byte from PERIPHERAL here *gdata = XGPIFSGLDATLNOX; } |
Рисунок 10-17. Функции транзакции однократного чтения
void TD_Init( void ) { BYTE xdata periph_status; ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform // TODO: configure other endpoints, etc. here // TODO: arm OUT buffer(s) here // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring //SYNCDELAY; //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) //SYNCDELAY; //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... // get status of peripheral function Peripheral_SetAddress( PERIPHCS ); Peripheral_SingleByteRead( &periph_status ); if( periph_status == AOKAY ) { // set it and forget it Peripheral_SetAddress( BURSTMODE ); } else { Peripheral_SetAddress( TRISTATE ); Housekeeping( ); EZUSB_Discon( TRUE ); // Disconnect from the bus for( EVER ) { // do not xfr peripheral data ; } } } |
Рисунок 10-18. Код инициализации для транзакций однократного чтения
Рисунок 10-19. Встроенное ПО запускает временную диаграмму однократной записи, WORDWIDE = 0
Рисунок 10-20. Временная диаграмма транзакции однократной записи
Рисунок 10-21. Настройка GPIFTool для временной диаграммы на рисунке 10-20
Транзакции однократной записи проще, чем транзакции однократного чтения, так как не требуется операция холостого чтения. Чтобы выполнить транзакцию однократной записи, необходимо:
Следующие фрагменты программы на C (рисунки 10-22 и 10-23) показывают, как выполнить транзакцию однократной записи в 8-разрядном режиме (WORDWIDE = 0):
#define PERIPHCS 0x00AB #define P_HSMODE 0x01 // prototypes void GpifInit( void ); // Set Address GPIFADR[8:0] to PERIPHERAL void Peripheral_SetAddress( WORD gaddr ) { GPIFADRH = gaddr >> 8; SYNCDELAY; GPIFADRL = ( BYTE )gaddr; // setup GPIF address } // write single byte to PERIPHERAL, using GPIF void Peripheral_SingleByteWrite( BYTE gdata ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } XGPIFSGLDATLX = gdata; // trigger GPIF single byte write transaction } |
Рисунок 10-22. Функции транзакции однократной записи
void TD_Init( void ) { ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform data // TODO: configure other endpoints, etc. here // TODO: arm OUT buffer(s) here // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring //SYNCDELAY; //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) //SYNCDELAY; //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... // tell peripheral we're going into high speed xfr mode Peripheral_SetAddress( PERIPHCS ); Peripheral_SingleByteWrite( P_HSMODE ); } |
Рисунок 10-23. Код инициализации для транзакций однократной записи
Временные диаграммы чтения и записи FIFO передают данные в ведомые FIFO FX2 и из них (см. Главу 9 "Ведомые FIFO"). Временная диаграмма запускается путём записи в EPxTRIG, где "x" означает FIFO (2, 4, 6 или 8), в которое (из которого) должны быть переданы данные, или в GPIFTRIG.
Временные диаграммы чтения или записи FIFO, как правило, передают большие потоки данных, а не отдельные байты или слова. Обычно временная диаграмма программируется так, чтобы завершиться, когда активизируется флаг FIFO (например, когда IN FIFO полон или OUT FIFO пуст) или после заданного количества транзакций. "Транзакция" есть передача одного байта (если WORDWIDE = 0) или слова (если WORDWIDE = 1) в или из FIFO. Используя терминологию GPIFTool, можно сказать, что транзакция может быть типа "Активная" (Active) или "Следующие данные" (Next Data).
Чтобы использовать счётчик транзакций для FIFO "x", загрузите в GPIFTCB3:0 желаемое число транзакций (от 1 до 4,294,967,295). Когда будет запущена временная диаграмма чтения или записи FIFO, GPIF передаст заданное количество байтов (или слов, если WORDWIDE = 1) автоматически.
Этот режим работы называется режимом длинной передачи (Long Transfer Mode). Когда счётчик транзакций используется таким образом, дескриптор временной диаграммы должен переходить в состояние ожидания после каждой транзакции.
При прохождении через состояние ожидания GPIF каждый раз декрементирует счётчик транзакций. Когда последний опустошается, временная диаграмма завершается и устанавливается бит DONE. В противном случае GPIF повторно выполняет весь дескриптор временной диаграммы. В режиме длинной передачи бит DONE не установится, пока счётчик транзакций не будет исчерпан.
Во время работы счётчика транзакций GPIF проверяет флаг заполнения (Full Flag) (для IN FIFO) или флаг опустошения (Empty Flag) (для OUT FIFO) на каждом проходе через состояние ожидания. Если флаг окажется установлен, GPIF приостановится, пока опасность переполнения/переопустошения не будет устранена, а затем автоматически продолжит работу. Так GPIF автоматически регулирует поток данных в режиме длинной передачи.
Регистры GPIFTCB3:0 доступны для чтения и обновляются по мере осуществления транзакций. Таким образом, процессор может читать счётчик транзакций в любое время.
Чтобы прочитать состояние счётчика транзакций в точке решения, установите GPIFREADYCFG.5 в 1 (при этом FX2 заменить вход RDY5 на состояние счётчика транзакций), а затем запустите транзакцию FIFO, которая использует счётчик транзакций. FX2 установит RDY5 в 1, когда счётчик транзакций опустошится.
Обычно это свойство используется для повторного запуска задачи управления. Оно позволяет использовать счётчик транзакций, не проходя через состояние ожидания после каждой транзакции.
Во время выполнения временной диаграммы GPIF может опрашивать флаги PF, EF или FF (текущего FIFO). Один из трёх флагов выбирается битами FS[1:0] в регистре EPxGPIFFLGSEL. Этот выбранный флаг называется флагом GPIF.
Когда EPxGPIFPFSTOP.0 устанавливается в 1, транзакции чтения и записи FIFO заканчиваются установкой флага GPIF. Когда это свойство используется, оно перекрывает счётчик транзакций: временная диаграмма GPIF завершается (DONE устанавливается в 1) только при установке флага GPIF.
Специального программирования дескрипторов временных диаграмм не требуется, и дескриптор временной диаграммы FIFO, который проходит через состояние ожидания в ходе каждой транзакции (то есть временной диаграммы, которая не использует счётчик транзакций) не изменяется. Автоматическое регулирование FIFO в состоянии ожидания всё равно происходит, поэтому нет опасности, что GPIF произведёт запись в полный FIFO или прочитает из пустого FIFO.
До тех пор, пока встроенное ПО не прервёт передачу GPIF записью в регистр GPIFABORT, только установка флага GPIF может завершить временную диаграмму и установить бит DONE.
Потенциально временная диаграмма может выполняться бесконечно, если
никогда не устанавливать флаг GPIF.
Флаг GPIF проверяется только во время прохождения через состояние
ожидания, и он не защёлкивается. Если в одном из состояний происходит
установка флага GPIF, и следующее состояние является точкой решения,
которая проверяет флаг GPIF и ждёт, пока он не будет сброшен,
чтобы разрешить цифровому автомату продолжить работу и перейти в состояние
ожидания, то GPIF автоматически вернётся в состояние 0, как если бы флаг
GPIF никогда не был установлен.
Рисунок 10-24. Встроенное ПО запускает временную диаграмму чтения FIFO
Рисунок 10-25. Пример транзакции чтения FIFO
Рисунок 10-26. Временная диаграмма транзакции чтения FIFO
Показанная выше временная диаграмма выполняется до опустошения счётчика транзакций (в этом примере - пока он не отсчитает 512). Счётчик транзакций декрементируется и опрашивается при каждом проходе через состояние ожидания.
Каждый повтор временной диаграммы считывает значение данных с шины данных FIFO в FIFO, затем декрементирует и проверяет счётчик транзакций. Когда он опустошается, бит DONE устанавливается в 1 и генерируется запрос прерывания GPIFDONE.
Рисунок 10-27. Настройка GPIFTool для временной диаграммы на рисунке 10-26
Обычно при выполнении чтения FIFO для временной диаграммы требуется только одно "Активировать" (Activate), после чего каждое выполнение "Активировать" инкрементирует внутренний указатель FIFO (и EPxBCH:L) автоматически.
Чтобы выполнить транзакцию чтения FIFO, необходимо:
Следующие фрагменты программы на C (рисунки от 10-28 до 10-31) показывают, как выполнить транзакцию чтения FIFO в 8-разрядном режиме (WORDWIDE = 0) при AUTOIN = 0:
#define GPIFTRIGRD 4 #define GPIF_EP2 0 #define GPIF_EP4 1 #define GPIF_EP6 2 #define GPIF_EP8 3 #define BURSTMODE 0x0000 #define HSPKTSIZE 512 ... ... ... ... ... // read(s) from PERIPHERAL, using GPIF and EPxFIFO void Peripheral_FIFORead( BYTE FIFO_EpNum ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 GPIF Done bit { ; } // trigger FIFO read transaction(s), using SFR GPIFTRIG = GPIFTRIGRD | FIFO_EpNum; // R/W=1, EP[1:0]=FIFO_EpNum // for EPx read(s) } // Set EP8GPIF Transaction Count void Peripheral_SetEP8GPIFTC( WORD xfrcnt) { EP8GPIFTCH = xfrcnt >> 8; // setup transaction count EP8GPIFTCL = ( BYTE )xfrcnt; } ... ... ... ... ... |
Рисунок 10-28. Функции транзакции чтения FIFO
void TD_Init( void ) { ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform data // TODO: configure other endpoints, etc. here EP8CFG = 0xE0; // EP8 is DIR=IN, TYPE=BULK SYNCDELAY; EP8FIFOCFG = 0x04; // EP8 is AUTOOUT=0, AUTOIN=0, ZEROLEN=1, WORDWIDE=0 // TODO: arm OUT buffer(s) here // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring //SYNCDELAY; //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) //SYNCDELAY; //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... // tell peripheral we're going into high speed xfr mode Peripheral_SetAddress( PERIPHCS ); Peripheral_SingleByteWrite( P_HSMODE ); // configure some GPIF registers Peripheral_SetAddress( BURSTMODE ); Peripheral_SetEP8GPIFTC( HSPKTSIZE ); } |
Рисунок 10-29. Код инициализации для транзакций чтения FIFO
void TD_Poll( void ) { ... ... ... ... ... if( ibn_event_flag ) { // host is asking for EP8 data Peripheral_FIFORead( GPIF_EP8 ); ibn_event_flag = 0; } if( gpifdone_event_flag ) { // GPIF currently pointing to EP8, last FIFO accessed if( !( EP2468STAT & 0x80 ) ) { // EP8F=0 when buffer available INPKTEND = 0x08; // Firmware commits pkt by writing 8 to INPKTEND gpifdone_event_flag = 0; } } ... ... ... ... ... } |
Рисунок 10-30. Чтение FIFO при AUTOIN = 0, передача пакетов через INPKTEND при SKIP=0
void TD_Poll( void ) { ... ... ... ... ... if( !( EP68FIFOFLGS & 0x10 ) ) { // EP8FF=0 when buffer available // host is taking EP8 data fast enough Peripheral_FIFORead( GPIF_EP8 ); } if( gpifdone_event_flag ) { // GPIF currently pointing to EP8, last FIFO accessed if( !( EP2468STAT & 0x80 ) ) { // EP8F=0 when buffer available // modify the data EP8FIFOBUF[ 0 ] = 0x02; // |
Рисунок 10-31. Чтение FIFO при AUTOIN = 0, передача пакетов через EPxBCL
Единственное различие между автоматическим (AUTOIN=1) и ручным (AUTOIN=0) режимами для пакетов IN заключается всвойстве длины пакета (EPxAUTOINLENH/L).
Рисунок 10-32. Транзакция чтения FIFO GPIF, (AUTOIN=1)
TD_Init(): EP8CFG = 0xE0; // EP8 is DIR=IN, TYPE=BULK SYNCDELAY; EP8FIFOCFG = 0x0C; // EP8 is AUTOOUT=0, AUTOIN=1, ZEROLEN=1, WORDWIDE=0 SYNCDELAY; EP8AUTOINLENH = 0x02; // if AUTOIN=1, auto commit 512 byte packets SYNCDELAY; EP8AUTOINLENL = 0x00; TD_Poll(): // no code necessary to xfr data from master to host! // AUTOIN=1 and EP8AUTOINLEN=512 auto commits packets, // in 512 byte chunks. |
Рисунок 10-33. Код транзакции чтения FIFO, AUTOIN=1
Рисунок 10-34. Вмешательство встроенного ПО, AUTOIN = 0/1
В ручном IN режиме (AUTOIN = 0) возможны следующие варианты встроенного ПО:
TD_Poll(): ... ... ... ... ... if( master_finished_longxfr( ) ) { // master currently points to EP8, last FIFO accessed if( !( EP68FIFOFLGS & 0x10 ) ) { // EP8FF=0 when buffer available INPKTEND = 0x08; // Firmware commits pkt // by writing #8 to INPKTEND release_master( EP8 ); } } ... ... ... ... ... |
Рисунок 10-35. Передача пакета путём записи в INPKTEND номера EPx (при SKIP = 0)
TD_Poll(): ... ... ... ... ... if( master_finished_longxfr( ) ) { // master currently points to EP8, last FIFO accessed if( !( EP68FIFOFLGS & 0x10 ) ) { // EP8FF=0 when buffer available INPKTEND = 0x88; // Firmware commits pkt // by writing 88 to INPKTEND release_master( EP8 ); } } ... ... ... ... ... |
Рисунок 10-36. Пропуск пакета при помощи записи в INPKTEND SKIP = 1
TD_Poll(): ... ... ... ... ... if( source_pkt_event ) { // 100msec background timer fired if( holdoff_master( ) ) { // signaled "busy" to master successful while( !( EP68FIFOFLGS & 0x20 ) ) { // EP8EF=0, when buffer not empty ; // wait 'til host takes entire FIFO data } // Reset FIFO 8. FIFORESET = 0x80; // Activate NAK-All to avoid race conditions. SYNCDELAY; FIFORESET = 0x08; // Reset FIFO 8. SYNCDELAY; FIFORESET = 0x00; // Deactivate NAK-All. EP8FIFOBUF[ 0 ] = 0x02; // |
Рисунок 10-37. Создание пакета IN при помощи записи в EPxBCH:L
Рисунок 10-38. Встроенное ПО запускает временную диаграмму записи в FIFO
Рисунок 10-39. Пример транзакции записи в FIFO
Рисунок 10-40. Временная диаграмма транзакции записи в FIFO.
Показанная выше временная диаграмма выполняется до опустошения счётчика транзакций (в этом примере - когда он отсчитает 512). Счётчик транзакций декрементируется и опрашивается на каждом проходе через состояние ожидания.
При каждом повторе временной диаграммы значение данных из FIFO выставляется на шину данных FIFO, а затем декрементируется и проверяется счётчик транзакций. Когда он опустошается, бит DONE устанавливается в 1 и генерируется запрос прерывания GPIFDONE.
Рисунок 10-41. Настройка GPIFTool для временной диаграммы на рисунке 10-40
Обычно при выполнении записи в FIFO для временной диаграммы достаточно только одного "NextData", после чего каждое выполнение "NextData" инкрементирует указатель FIFO.
Чтобы выполнить транзакцию записи в FIFO, необходимо:
Следующие фрагменты программы на C (рисунки от 10-42 до 10-44) показывают, как выполнить транзакцию записи в FIFO в 8-разрядном режиме (WORDWIDE = 0) при AUTOOUT = 0:
#define GPIFTRIGWR 0 #define GPIF_EP2 0 #define GPIF_EP4 1 #define GPIF_EP6 2 #define GPIF_EP8 3 #define BURSTMODE 0x0000 #define HSPKTSIZE 512 ... ... ... ... ... // write byte(s) to PERIPHERAL, using GPIF and EPxFIFO void Peripheral_FIFOWrite( BYTE FIFO_EpNum ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 Done bit { ; } // trigger FIFO write transaction(s), using SFR GPIFTRIG = FIFO_EpNum; // R/W=0, EP[1:0]=FIFO_EpNum for EPx write(s) } // Set EP2GPIF Transaction Count void Peripheral_SetEP2GPIFTC( WORD xfrcnt) { EP2GPIFTCH = xfrcnt >> 8; // setup transaction count EP2GPIFTCL = ( BYTE )xfrcnt; } ... ... ... ... ... |
Рисунок 10-42. Функции транзакции записи в FIFO
void TD_Init( void ) { ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform data // TODO: configure other endpoints, etc. here EP2CFG = 0xA2; // EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x SYNCDELAY; EP2FIFOCFG = 0x00; // EP2 is AUTOOUT=0, AUTOIN=0, ZEROLEN=0, WORDWIDE=0 SYNCDELAY; // "all" EP2 buffers automatically arm when AUTOOUT=1 // TODO: arm OUT buffer(s) here EP2BCL = 0x80; // write BCL w/skip=1 SYNCDELAY; EP2BCL = 0x80; // write BCL w/skip=1 SYNCDELAY; // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... // tell peripheral we're going into high speed xfr mode Peripheral_SetAddress( PERIPHCS ); Peripheral_SingleByteWrite( P_HSMODE ); // configure some GPIF control registers Peripheral_SetAddress( BURSTMODE ); } |
Рисунок 10-42. Код инициализации для транзакций записи в FIFO
void TD_Poll( void ) { ... ... ... ... ... if( !( EP2468STAT & 0x01 ) ) { // EP2EF=0 when FIFO "not" empty, host sent pkt. EP2BCL = 0x00; // SKIP=0, pass buffer on to master if( gpifdone_event_flag ) { Peripheral_SetEP2GPIFTC( HSPKTSIZE ); Peripheral_FIFOWrite( GPIF_EP2 ); gpifdone_event_flag = 0; } } ... ... ... ... ... } |
Рисунок 10-44. Запись в FIFO при AUTOOUT = 0, пакеты передаются через EPxBCL
Для получения максимальной полосы пропускания хост и ведущий соединяются напрямую, когда AUTOOUT = 1. Данные из OUT FIFO в обход процессора автоматически передаются в хост.
Рисунок 10-45. Поток данных идёт мимо процессора, AUTOOUT = 1
TD_Init(): ... ... ... ... ... REVCTL = 0x03; // MUST set REVCTL.0 and REVCTL.1 to 1 SYNCDELAY; EP2CFG = 0xA2; // EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x SYNCDELAY; FIFORESET = 0x80; // Reset the FIFO SYNCDELAY; FIFORESET = 0x02; SYNCDELAY; FIFORESET = 0x00; SYNCDELAY; EP2FIFOCFG = 0x10; // EP2 is AUTOOUT=1, AUTOIN=0, ZEROLEN=0, WORDWIDE=0 SYNCDELAY; OUTPKTEND = 0x82; // Arm both EP2 buffers to "prime the pump" SYNCDELAY; OUTPKTEND = 0x82; ... ... ... ... ... |
Рисунок 10-46. Пример TD_Init: конфигурирование, AUTOOUT = 1
TD_Poll(): ... ... ... ... ... // no code necessary to xfr data from host to master! // AUTOOUT=1 and SIZE=0 auto commits packets, // in 512 byte chunks. ... ... ... ... ... |
Рисунок 10-47. Код транзакции записи в FIFO, AUTOOUT = 1
Рисунок 10-48. Встроенное ПО может пропускать или передавать данные
TD_Init(): ... ... ... ... ... EP2CFG = 0xA2; // EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x SYNCDELAY; EP2FIFOCFG = 0x00; // EP2 is AUTOOUT=0, AUTOIN=0, ZEROLEN=0, WORDWIDE=0 SYNCDELAY; // OUT endpoints do NOT come up armed EP2BCL = 0x80; // arm first buffer by writing BC w/skip=1 SYNCDELAY; EP2BCL = 0x80; // arm second buffer by writing BC w/skip=1 ... ... ... ... ... |
Рисунок 10-49. Код инициализации для AUTOOUT = 0
В ручном режиме вывода (OUT) возможны следующие варианты встроенного ПО:
TD_Poll(): ... ... ... ... ... if( !( EP24FIFOFLGS & 0x02 ) ) { // EP2EF=0 when FIFO "not" empty, host sent pkt. OUTPKTEND = 0x02; // SKIP=0, pass buffer on to master } ... ... ... ... ... |
Рисунок 10-50. Передача пакета OUT путём записи в OUTPKTEND SKIP=0
TD_Poll(): ... ... ... ... ... if( !( EP24FIFOFLGS & 0x02 ) ) { // EP2EF=0 when FIFO "not" empty, host sent pkt. OUTPKTEND = 0x82; // SKIP=1, do NOT pass buffer on to master } ... ... ... ... ... |
Рисунок 10-51. Пропуск пакета OUT путём записи в OUTPKTEND SKIP=1
Во всех случаях буфер OUT автоматически перезаряжается для приёма
следующего пакета.
Подробное описание бита SKIP см. в разделе 8.6.2.4.
TD_Poll(): ... ... ... ... ... if( EP24FIFOFLGS & 0x02 ) { SYNCDELAY; // FIFORESET = 0x80; // nak all OUT pkts. from host SYNCDELAY; // FIFORESET = 0x02; // advance all EP2 buffers to cpu domain SYNCDELAY; // EP2FIFOBUF[0] = 0xAA; // create newly sourced pkt. data SYNCDELAY; // EP2BCH = 0x00; SYNCDELAY; // EP2BCL = 0x01; // commit newly sourced pkt. to interface fifo // beware of "left over" uncommitted buffers SYNCDELAY; // OUTPKTEND = 0x82; // skip uncommitted pkt. (second pkt.) // note: core will not allow pkts. to get out of sequence SYNCDELAY; // FIFORESET = 0x00; // release "nak all" } ... ... ... ... ... |
Рисунок 10-52. Генерация пакета OUT (AUTOOUT = 0)
Когда встроенное ПО пропускает пакет, мастер не уведомляется.
OUT FIFO Не передаёт данные хосту во время сброса по включению питания. Поэтому в подпрограмме инициализации встроенное ПО должно пропустить n пакетов (где n = 2, 3 или 4 в зависимости от глубины буферизации), чтобы удостовериться, что весь FIFO прередан в хост. См. рисунок 10-53.
TD_Init(): ... ... ... ... ... EP2CFG = 0xA2; // EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x SYNCDELAY; EP2FIFOCFG = 0x00; // EP2 is AUTOOUT=0, AUTOIN=0, ZEROLEN=0, WORDWIDE=0 SYNCDELAY; // OUT endpoints do NOT come up armed EP2BCL = 0x80; // arm first buffer by writing BC w/skip=1 SYNCDELAY; EP2BCL = 0x80; // arm second buffer by writing BC w/skip=1 ... ... ... ... ... |
Рисунок 10-53. Проверка того, что FIFO очищен после сброса по включению питания
GPIF может быть сконфигурирован для автоматического повторения транзакций без вмешательства встроенного ПО. Эти пакетные транзакции (которые дожны быть всегда транзакциями чтения FIFO или записи в FIFO) могут управляться счётчиком транзакций, флагом GPIF_PF или регистром GPIFABORT.
Следующие фрагменты программы на C (рисунки от 10-54 до 10-57) показывают, как выполнить пакетную транзакцию чтения FIFO, используя GPIF_PF в 8-разрядном режиме (WORDWIDE=0) и при AUTOIN=0:
#define GPIFTRIGRD 4 #define GPIF_EP2 0 #define GPIF_EP4 1 #define GPIF_EP6 2 #define GPIF_EP8 3 #define BURSTMODE 0x0000 #define HSPKTSIZE 512 ... ... ... ... ... // read(s) from PERIPHERAL, using GPIF and EPxFIFO void Peripheral_FIFORead( BYTE FIFO_EpNum ) { while( !( GPIFTRIG & 0x80 ) ) // poll GPIFTRIG.7 GPIF Done bit { ; } // trigger FIFO read transaction(s), using SFR GPIFTRIG = GPIFTRIGRD | FIFO_EpNum; // R/W=1, EP[1:0]=FIFO_EpNum // for EPx read(s) } // Set EP8GPIF Transaction Count void Peripheral_SetEP8GPIFTC( WORD xfrcnt) { EP8GPIFTCH = xfrcnt >> 8; // setup transaction count EP8GPIFTCL = ( BYTE )xfrcnt; } ... ... ... ... ... |
Рисунок 10-54. Функции транзакции пакетного чтения FIFO
void TD_Init( void ) { ... ... ... ... ... GpifInit(); // Configures GPIF from GPIFTool generated waveform data // TODO: configure other endpoints, etc. here EP8CFG = 0xE0; // EP8 is DIR=IN, TYPE=BULK SYNCDELAY; EP8FIFOCFG = 0x04; // EP8 is AUTOOUT=0, AUTOIN=0, ZEROLEN=1, WORDWIDE=0 SYNCDELAY; // TODO: arm OUT buffer(s) here // setup INT4 as internal source for GPIF interrupts // using INT4CLR (SFR), automatically enabled //INTSETUP |= 0x03; //Enable INT4 Autovectoring //SYNCDELAY; //GPIFIE = 0x03; // Enable GPIFDONE and GPIFWF interrupt(s) //SYNCDELAY; //EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4)=1 // TODO: configure GPIF interrupt(s) to meet your needs here ... ... ... ... ... // tell peripheral we're going into high speed xfr mode Peripheral_SetAddress( PERIPHCS ); Peripheral_SingleByteWrite( P_HSMODE ); // configure some GPIF registers Peripheral_SetAddress( BURSTMODE ); } |
Рисунок 10-55. Инициализация для транзакций пакетного чтения FIFO
void TD_Poll( void ) { ... ... ... ... ... if( ibn_event_flag ) { // host is asking for EP8 data Peripheral_SetEP8GPIFTC( HSPKTSIZE ); Peripheral_FIFORead( GPIF_EP8 ); ibn_event_flag = 0; } if( gpifdone_event_flag ) { // GPIF currently pointing to EP8, last FIFO accessed if( !( EP2468STAT & 0x80 ) ) { // EP8F=0 when buffer available INPKTEND = 0x08; // Firmware commits pkt // by writing #8 to INPKTEND gpifdone_event_flag = 0; } } // decide how GPIF transitions to DONE for FIFO Transactions if( gpif_pf_event_flag ) { EP8GPIFPFSTOP = 0x01; // set bit0=1 to use GPIF_PF } else { EP8GPIFPFSTOP = 0x00; // set bit0=0 to use TC } ... ... ... ... ... } |
Рисунок 10-56. Пример транзакции пакетного чтения FIFO. Для передачи в INPKTEND устанавливается SKIP=0
void TD_Poll( void ) { ... ... ... ... ... if( !( EP68FIFOFLGS & 0x10 ) ) { // EP8FF=0 when buffer available // host is taking EP8 data fast enough Peripheral_SetEP8GPIFTC( HSPKTSIZE ); Peripheral_FIFORead( GPIF_EP8 ); } if( gpifdone_event_flag ) { // GPIF currently pointing to EP8, last FIFO accessed if( !( EP2468STAT & 0x80 ) ) { // EP8F=0 when buffer available // modify the data EP8FIFOBUF[ 0 ] = 0x02; // |
Рисунок 10-57. Пример пакетной транзакции чтения FIFO, запись в EPxBCL для передачи
Специально для реализации интерфейса UDMA (Ultra-ATA) в FX2 имеются дополнительные регистры. За более подробной информацией обращайтесь, пожалуйста, в Cypress Semiconductor Applications Department.