На главную страницу

    К оглавлению

Перевод избранного из
EZ-USB FX2 Manual Technical Reference

   Перевод сделан по файлу EZ-USB_FX2_TRM_version2-2.pdf. Это EZ-USB FX2 Technical Reference Manual v2.2.
    ©CОПЫРИГХТ: Перевёл и положил на свою страничку http://www.dsioffe.narod.ru/ Дмитрий Иоффе.

Глава 10
Универсальный программируемый интерфейс (GPIF)

10.1 Введение

    Универсальный программируемый интерфейс (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 любым способом.

Место GPIF в системе 
FX2

    Рисунок 10-1. Место GPIF в системе FX2

    На рисунке 10-2 приведён пример простой транзакции GPIF. Для этой транзакции GPIF генерирует адрес (GPIFADR[8:0]), выставляет код на шину данных FIFO (FD[15:0]), затем ждёт низкого уровня внешнего квитирующего сигнала (RDY0), после чего устанавливает низкий уровень на выходе CTL0. Когда на RDY0 возвращается высокий уровень, GPIF устанавливает высокий уровень на CTL0 и затем переводит шину данных в третье состояние.

Пример временной 
диаграммы GPIF

    Рисунок 10-2. Пример временной диаграммы GPIF


10.1.1 Типичный интерфейс 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 и периферийным устройством.

Интерфейс между 
EZ-USB FX2 и периферией

    Рисунок 10-3. Интерфейс между EZ-USB FX2 и периферией

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

Аппаратная часть

    В таблице 10-1 перечислены регистры, связанные с аппаратной частью GPIF. Детальное описание каждого регистра можно найти в главе 15 "Регистры".

    Таблица 10-1. Регистры, связанные с аппаратной частью GPIF

Регистры, связанные с аппаратной частью GPIF

    Обратите внимание: "x" в именах этих регистров может означать 2, 4, 6 или 8. Конечные точки 0 и 1 не связаны с GPIF.


10.2.1 Внешний интерфейс GPIF

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

    Сигналы интерфейса GPIF показаны в таблице 10-2.

Таблица 10-2. Описание выводов GPIF
Вывод Вход/Выход Описание
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.


10.2.2 Конфигурация выводов GPIF по умолчанию

    FX2 выходит из состояния сброса с линиями ввода-вывода в режиме "Порты" ("Ports"), не в режиме "GPIF Master". Чтобы сконфигурировать выводы для режима GPIF, надо установить биты IFCFG[1:0] в регистре IFCONFIG в 10 (подробнее см. таблицу 13-10, "Выбор функций линий ввода-вывода в IFCFG").


10.2.3 Шесть управляющих выходных сигналов

    В корпусах со 100 и 128 выводами наружу выведены все шесть управляющих выходов, CTL[5:0]. В корпусе с 56 выводами выведены только три из этих сигналов, CTL[2:0]. Скорость переключений на этих выводах может быть запрограммирована вплоть до одного переключения за период тактовой частоты (каждые 20,8 нс, если IFCLK работает от 48 МГц).

    По умолчанию на этих линиях высокий уровень.

10.2.3.1 Режимы управляющих выходов

    Управляющие выходы GPIF CTL[5:0] могут работать в следующих режимах:

    Если CTL[3:0] сконфигурированы как тристабильные, то CTL[5:4] недоступны.

Таблица 10-3. Режимы выходов CTL[5:0]
TRICTL (GPIFCTLCFG.7) GPIFCTLCFG[6:0] CTL[3:0] CTL[5:4]
0 0 КМОП, не тристабильные КМОП, не тристабильные
0 1 Открытый сток Открытый сток
1 X КМОП, тристабильные Недоступны


10.2.4 Шесть входных сигналов готовности

    В корпусах со 100 и 128 выводами наружу выведены все шесть входов готовности, RDY[5:0]. В корпусе с 56 выводами выведены только два из этих сигналов, RDY[1:0].

    Входы готовности могут опрашиваться синхронно или асинхронно. Когда GPIF находится в асинхронном режиме (SAS=0), входы RDY неизбежно немного запаздывают (примерно на 24 нс при 48 МГц IFCLK). Другими словами, когда GPIF "смотрит" на входы RDY, он видит их состояние, которое было 24 нс назад.


10.2.5 Девять адресных выходов GPIF

    В GPIF имеется девять адресных линий, GPIFADR[8:0]. Если адресные линии сконфигурированы как выходы, запись в регистры GPIFADRH:L управляет этими выходами непосредственно. Механизм GPIF может также инкрементировать их код под управлением дескрипторов временных диаграмм. Адресные линии GPIF можно перевести в третье состояние, сбросив ассоциированные биты PORTxCFG и OEx (см. пункт 13.3.3 "Альтернативные функции порта C" и пункт 13.3.4 "Альтернативные функции порта E").


10.2.6 Три выходных сигнала GSTATE

    Три выходных линии GPIF GSTATE[2:0] доступны при альтернативной конфигурации PORTE[2:0]. По умолчанию это входы общего назначения. Установка GSTATE (IFCONFIG2) в 1 включит альтернативную конфигурацию и перекроет установку битов PORTECFG[2:0].

    Выводы GSTATE[2:0] содержат номер текущего состояния GPIF. Это свойство обычно используется только для отладки временных диаграмм GPIF.


10.2.7 8/16 разрядная шина данных, WORDWIDE=1 (по умолчанию) и WORDWIDE=0

    Когда FX2 сконфигурирован для ведущего режима (Master mode) GPIF, PORTB всегда конфигурируется как FD[7:0].

    Если любой из битов WORDWIDE установлен в 1, то PORTD автоматически конфигурируется как FD[15:8]. Если все биты WORDWIDE сброшены, PORTD доступен для ввода-вывода общего назначения.


10.2.8 Порядок байтов для 16-битных транзакций GPIF

    Данные пересылаются через USB пакетами 8-битных байтов, а не 16-битных слов. Когда ширина шины данных FIFO 16 битов, первый байт каждой пары, проходящей через USB, передаётся через FD[7:0], а второй байт - через FD[15:8].


10.2.9 Тактирование интерфейса

    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 МГц.

Конфигурирование IFCLK

    Рисунок 10-4. Конфигурирование IFCLK

Получение нужного 
времени установления инвертированием выхода IFCLK

    Рисунок 10-5. Получение нужного времени установления инвертированием выхода IFCLK


10.2.10 Подключение сигналов GPIF к аппаратуре

    Первый шаг при создании интерфейса между GPIF FX2 и внешней периферией - это создание аппаратных связей.

  1. Определяем настройку IFCLK. Решаем, какой интерфейс использовать: асинхронный или синхронный. Если синхронный, выбираем между внутренним и внешним тактированием. Если выбрали внутреннее, выбираем между 30 и 48 МГц. Если внешнее, убедимся, что внешняя тактовая частота лежит в диапазоне от 5 до 48 МГц.
  2. Выбираем требуемый размер шины данных FIFO. Если ширина шины данных 8 битов, используем выводы FD[7:0] и устанавливаем WORDWIDE=0. Если она равна 16 битам, используем FD[15:0] и устанавливаем WORDWIDE=1.
  3. Назначаем сигналы CTLx. Создаём список всех выходных сигналов интерфейса для управления периферией и назначаем им выходы CTL[5:0]. Если требуется больше сигналов, чем доступно выходов CTL, надо использовать сигналы ввода-вывода общего назначения (не GPIF), управляемые через встроенное ПО FX2. В этом случае выходы CTL должны предназначаться только для сигналов, участвующих в передаче данных.
  4. Назначаем сигналы RDYn. Создаём список всех входных сигналов, поступающих от периферии, и назначаем им входы RDY[5:0]. Если входных сигналов больше, чем доступно входов RDY, то встроенное ПО FX2 должно опрашивать линии ввода-вывода, не принадлежащие GPIF. В этом случае входы RDY должны использоваться только для сигналов, опрашиваемых в ходе передачи данных.
  5. Определяем подключение адресных линий GPIF. Если в интерфейсе используется адресная шина, используем сигналы GPIFADR[8:0] для младших битов и линии ввода-вывода общего назначения для старших битов адреса. Если адресные выводы не нужны (например, для периферийного устройства типа FIFO), их можно оставить неподключёнными.


10.2.11 Пример подключения GPIF

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

Таблица 10-4. Пример подключения GPIF к аппаратуре
Шаг Результат Сделанные соединения
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].

    Для других, более сложных, интерфейсов процесс остаётся тем же самым.

10.3 Программирование временных диаграмм GPIF

   Каждый дескриптор временных диаграмм GPIF может определять до семи состояний. В каждом состоянии GPIF может быть запрограммирован так, чтобы:

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

   Состояния, в которых происходит опрос и переход, называются точками решения (Decision Points, DP). Остальные состояния называются точками не-решения (Non-Decision Points, NDP).

Общее представление
  о цифровом автомате GPIF

   Рисунок 10-6. Общее представление о цифровом автомате GPIF


10.3.1 Регистры GPIF

   Два блока регистров, управляющих цифровым автоматом GPIF:

   До тех пор, пока встроенное ПО не загрузит регистры конфигурации и регистры временных диаграмм, GPIF не может начать передачу данных.

   Доступ к регистрам временных диаграмм разрешается только тогда, когда FX2 находится в режиме GPIF (т.е. IFCFG[1:0] = 10). Запись в регистры временных диаграмм возможна только тогда, когда механизм GPIF остановлен (т.е. DONE = 1).

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


10.3.2 Программирование временных диаграмм GPIF

    "Программой" для 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.

10.3.2.1 Состояние ожидания (IDLE) GPIF

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

    Для завершения транзакции GPIF программа GPIF должна перейти к состоянию ожидания, независимо от состояния, в котором эта программа находится в настоящий момент. Например, временная диаграмма GPIF может быть задана программой, которая содержит только два программируемых состояния, S0 и S1. Чтобы завершиться, программа должна из состояния S1 (или S0) перейти в S7.

    Состояние сигналов GPIF во время состояния ожидания определяется содержимым регистров GPIFIDLECS и GPIFIDLECTL.

   Когда временная диаграмма уже началась, другая временная диаграмма не может стартовать, пока первая не закончится. Об окончании временной диаграммы сообщает бит DONE (GPIFIDLECS.7 или GPIFTRIG.7) или, опционально, прерывание GPIFDONE.

    Note! Важно: при возникновении исключительной ситуации (запись в регистр GPIFABORT для принудительного завершения временной диаграммы) не допускается запись в какие-либо регистры, связанные с GPIF (включая регистры временных диаграмм), пока GPIF занят. Это может привести к непредсказуемому поведению и повреждению данных.

10.3.2.1.1 Шина данных GPIF в состоянии ожидания

   В состоянии ожидания выходы шины данных GPIF могут быть активны или находиться в третьем состоянии, в зависимости от состояния бита IDLEDRV (GPIFIDLECS.0):

10.3.2.1.2 Выходы CTL в состоянии ожидания

   В состоянии ожидания состояние выходов CTL[5:0] зависит от следующих битов:

   Комбинация этих битов определяет состояние CTL[5:0] следующим образом:

   Эти зависимости показаны в таблице 10.5.

Таблица 10-5. Управляющие выходы (CTLn) во время состояния ожидания
Таблица 10-5

10.3.2.2. Определение состояний

   Каждая временная диаграмма состоит из некоторого числа состояний, каждое из которых определяется 32-разрядной инструкцией состояния. Каждое состояние может принадлежать к одному из двух основных типов: точка не-решения (Non-Decision Point, NDP) или точка решения (Decision Point, DP).

   Для временных диаграмм "записи" шина данных в каждом состоянии может быть активна или находиться в третьем состоянии. Для временных диаграмм "чтения" шина данных в каждом состоянии может опрашиваться или не опрашиваться.

10.3.2.2.1. Состояния в точках не-решения (NDP)

   Состояние управляющих выходов (CTLx) в точках не-решения определяется инструкциями GPIF. На выходе может быть 0, 1 или третье состояние. Длительность состояний NDP программируется и задаётся в циклах IFCLK.

   Рисунок 10-7 иллюстрирует базовую концепцию состояний NDP. Показана временная диаграмма записи, и для упрощения все состояния имеют одинаковую длительность. На рисунке показан только один управляющий выход из шести, CTL0.

Базовая концепция 
состояний NDP

   Рисунок 10-7. Базовая концепция состояний NDP

   Рассмотрим рисунок 10-7:

В состоянии 0: В состоянии 1: В состоянии 2: В состоянии 3: В состоянии 4: В состоянии 5: В состоянии 6:

   Так как все состояния в этом примере закодированы как NDP, GPIF автоматически переходит из состояния S6 в состояние ожидания S7. В этом состоянии GPIF ждёт, пока встроенное ПО запустит следующую временную диаграмму.

   Состояния 2 и 3 в этом примере идентичны, как и состояния 5 и 6. В реальном приложении можно делать иначе: необязательно дублировать состояния, чтобы "растягивать" их, можно назначать длительность каждого состояния не-решения в циклах IFCLK. Если для данной временной диаграммы определено меньше семи состояний, состояние ожидания автоматически наступает после последнего запрограммированного состояния. Инструкция для этого последнего запрограммированного состояния должна в явном виде содержать переход в состояние ожидания.

10.3.2.2.2. Состояния в точках решения (DP)

    Любое состояние может быть сделано точкой решения (Decision Point, DP). DP позволяет механизму GPIF опрашивать два сигнала (это может быть один и тот же сигнал), при необходимости выполнять булевскую операцию над полученными значениями, затем переходить в другое состояние (или циклически возвращаться в то же самое, сохраняя тем самым текущее состояние) в зависимости от результата.

    Если инструкция состояния включает задачу управления (продвижение указателя FIFO, инкремент адреса GPIFADR и т.д.), то эта задача всегда выполняется один раз при входе в состояние, независимо от того, является ли это состояние DP или NDP. Если это состояние - DP, циклически возвращающееся в себя, оно может быть запрограммировано на повторное выполнение задачи управления на каждом цикле.

    В точке решения GPIF может выполнять простые задачи (например, ожидать, пока на линии RDY появится низкий уровень, чтобы перейти в следующее состояние). Состояние точки решения может также выполнять более сложные задачи, переходя в одно состояние, если в результате опроса сигналов получается логическая 1, и в другое, если получается 0.

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

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

    Инструкция состояния также задаёт, в какое состояние переходить, если результат логического выражения равен 0, а в какое - если 1.

    Ниже приведён пример временной диаграммы, созданной с использованием одной точки решения (состояние 1). Состояния не-решения используются для паузы во временной диаграмме.

Рисунок 10-8. Одна 
точка решения: состояния ожидания вставляются до тех пор, пока на RDY0 не 
появится низкий уровень

    Рисунок 10-8. Одна точка решения: состояния ожидания вставляются до тех пор, пока на RDY0 не появится низкий уровень

Рисунок 10-9. Одна 
точка решения: состояния ожидания не вставляются: в точке решения S1 на
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.

    Note! Несмотря на то, что на рисунке 10-8 показано, что GPIF переходит непосредственно из состояния 0 в состояние 2, это не совсем так. Даже если перед тем, как GPIF входит в состояние 1, на RDY уже низкий уровень, GPIF проводит один такт IFCLK в состоянии 1.


10.3.3 Повторное выполнение задачи в состоянии DP

    В простых примерах DP, показанных ранее в этой главе, задача управления (например, вывод слова на FD[15:0] и инкремент GPIFADR[8:0] выполняется только один раз в начале состояния DP, а затем GPIF ждёт, опрашивая вход RDYx, пока он не "скажет" GPIF перейти в следующее состояние.

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

Рисунок 10-10. Повторное
выполнение задачи в состоянии DP

   Рисунок 10-10. Повторное выполнение задачи в состоянии DP

Рисунок 10-11. 
Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-10

   Рисунок 10-11. Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-10

Рисунок 10-12. 
Состояние DP, в котором НЕ происходит повторное выполнение задачи

   Рисунок 10-12. Состояние DP, в котором НЕ происходит повторное выполнение задачи

Рисунок 10-13. 
Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-12

   Рисунок 10-13. Настройка утилиты GPIFTool для временной диаграммы на рисунке 10-12


Инструкции состояния

    Характеристики каждого состояния определяются четырьмя байтами инструкции состояния. Эти четыре байта называются LENGTH / BRANCH, OPCODE, LOGIC FUNCTION и OUTPUT (ДЛИНА / ВЕТВЛЕНИЕ, КОД ОПЕРАЦИИ, ЛОГИЧЕСКАЯ ФУНКЦИЯ и ВЫХОД).

    Обратите внимание, что инструкции состояния по-разному интерпретируются для точек решения (DP=1) и точек не-решения (DP=0).

    Инструкция состояния для точки не-решения (DP=0)

DP=0

    Инструкция состояния для точки решения (DP=1)

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.3.4.1 Структура дескрипторов временных диаграмм

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

Таблица 10-6. Адреса дескрипторов временных диаграмм
Таблица 10-6

    Внутри каждого дескриптора временной диаграммы инструкции состояния упакованы так, как описано в таблице 10-7 "Структура дескриптора временной диаграммы 0". Дескриптор временной диаграммы 0 показан для примера. Другие дескрипторы построены так же, но имеют бОльшие адреса XDATA.

Таблица 10-7. Структура дескриптора временной диаграммы 0
Таблица 10-7



10.4. Встроенное программное обеспечение (Firmware)


Таблица 10-8. Регистры, связанные со встроенным ПО GPIF
Таблица 10-8

    В этих именах регистров "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.4.1. Транзакции однократного чтения

Рисунок 10-14. 
Встроенное ПО запускает временную диаграмму однократного чтения, WORDWIDE 
= 0
*Все биты EPx WORDWIDE для 8-разрядных транзакций должны быть сброшены. Если любой из битов EPx WORDWIDE установлен в 1, то однократная транзакция будет 16-разрядной.

    Рисунок 10-14. Встроенное ПО запускает временную диаграмму однократного чтения, WORDWIDE = 0

Рисунок 10-15. 
Временная диаграмма однократного чтения

    Рисунок 10-15. Временная диаграмма однократного чтения

Рисунок 10-16. 
Настройка GPIGTool для временной диаграммы на рисунке 10-15

    Рисунок 10-16. Настройка GPIGTool для временной диаграммы на рисунке 10-15

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

  1. Инициализировать регистры конфигурации GPIF и дескрипторы временных диаграмм.
  2. Выполнить холостое чтение регистра XGPIFSGLDATLX, чтобы запустить одну транзакцию.
  3. Подождать, пока GPIF покажет, что транзакция завершена. Когда транзакция завершается, бит DONE (GPIFIDLECS.7 или GPIFTRIG.7) установится в 1. Кроме того, если это разрешено, генерируется прерывание GPIFDONE.
  4. В зависимости от ширины шины и необходимости запуска следующей транзакции, прочитанные данные могут быть полученны из регистра XGPIFSGLDATH, XGPIFSGLDATLX и/или XGPIFSGLDATLNOX (или из пространства SFR копий этих регистров):
    Только в 16-разрядном режиме старший байт данных FD[15:8] читается из регистра XGPIFSGLDATH.
    В 8- и 16-разрядном режимах младший бит данных читается одним из следующих способов:

    Следующий фрагмент программы на 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.4.2. Транзакции однократной записи

Рисунок 10-19. 
Встроенное ПО запускает временную диаграмму однократной записи, WORDWIDE = 
0
*Все биты EPx WORDWIDE для 8-разрядных транзакций должны быть сброшены. Если любой из битов EPx WORDWIDE установлен, то однократная транзакция будет 16-разрядной.

    Рисунок 10-19. Встроенное ПО запускает временную диаграмму однократной записи, WORDWIDE = 0

Рисунок 10-20. 
Временная диаграмма транзакции однократной записи

    Рисунок 10-20. Временная диаграмма транзакции однократной записи

Рисунок 10-21. 
Настройка GPIFTool для временной диаграммы на рисунке 10-20

    Рисунок 10-21. Настройка GPIFTool для временной диаграммы на рисунке 10-20

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

  1. Инициализировать регистры конфигурации GPIF и дескрипторы временных диаграмм.
  2. В 16-разрядном режиме (WORDWIDE = 1) записать старший байт данных в регистр XGPIFSGLDATH, а затем записать младший байт в регистр XGPIFSGLDATLX, запустив тем самым транзакцию однократного чтения.
    В 8-разрядном режиме просто записать данные в регистр XGPIFSGLDATLX, запустив тем самым транзакцию однократного чтения.
  3. Подождать, пока GPIF покажет,что транзакция выполнена. Когда транзакция завершится, бит DONE (GPIFIDLECS.7 или GPIFTRIG.7) установится в 1. Кроме того, если это разрешено, генерируется прерывание GPIFDONE.

    Следующие фрагменты программы на 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. Код инициализации для транзакций однократной записи


10.4.3. Транзакции чтения и записи FIFO

    Временные диаграммы чтения и записи 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).

10.4.3.1. Счётчик транзакций

    Чтобы использовать счётчик транзакций для 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 доступны для чтения и обновляются по мере осуществления транзакций. Таким образом, процессор может читать счётчик транзакций в любое время.

10.4.3.2. Чтение состояния счётчика транзакций в точке решения (DP)

    Чтобы прочитать состояние счётчика транзакций в точке решения, установите GPIFREADYCFG.5 в 1 (при этом FX2 заменить вход RDY5 на состояние счётчика транзакций), а затем запустите транзакцию FIFO, которая использует счётчик транзакций. FX2 установит RDY5 в 1, когда счётчик транзакций опустошится.

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


10.4.4. Выбор флага GPIF

    Во время выполнения временной диаграммы GPIF может опрашивать флаги PF, EF или FF (текущего FIFO). Один из трёх флагов выбирается битами FS[1:0] в регистре EPxGPIFFLGSEL. Этот выбранный флаг называется флагом GPIF.


10.4.5. Остановка флагом GPIF

    Когда EPxGPIFPFSTOP.0 устанавливается в 1, транзакции чтения и записи FIFO заканчиваются установкой флага GPIF. Когда это свойство используется, оно перекрывает счётчик транзакций: временная диаграмма GPIF завершается (DONE устанавливается в 1) только при установке флага GPIF.

    Специального программирования дескрипторов временных диаграмм не требуется, и дескриптор временной диаграммы FIFO, который проходит через состояние ожидания в ходе каждой транзакции (то есть временной диаграммы, которая не использует счётчик транзакций) не изменяется. Автоматическое регулирование FIFO в состоянии ожидания всё равно происходит, поэтому нет опасности, что GPIF произведёт запись в полный FIFO или прочитает из пустого FIFO.

Note! До тех пор, пока встроенное ПО не прервёт передачу GPIF записью в регистр GPIFABORT, только установка флага GPIF может завершить временную диаграмму и установить бит DONE.

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

10.4.5.1. Выполнение транзакции чтения FIFO

Рисунок 10-24. 
Встроенное ПО запускает временную диаграмму чтения FIFO

    Рисунок 10-24. Встроенное ПО запускает временную диаграмму чтения FIFO

Рисунок 10-25. 
Пример транзакции чтения FIFO

    Рисунок 10-25. Пример транзакции чтения FIFO

Рисунок 10-26. 
Временная диаграмма транзакции чтения FIFO

    Рисунок 10-26. Временная диаграмма транзакции чтения FIFO

    Показанная выше временная диаграмма выполняется до опустошения счётчика транзакций (в этом примере - пока он не отсчитает 512). Счётчик транзакций декрементируется и опрашивается при каждом проходе через состояние ожидания.

    Каждый повтор временной диаграммы считывает значение данных с шины данных FIFO в FIFO, затем декрементирует и проверяет счётчик транзакций. Когда он опустошается, бит DONE устанавливается в 1 и генерируется запрос прерывания GPIFDONE.

Рисунок 10-27. 
Настройка GPIFTool для временной диаграммы на рисунке 10-26

    Рисунок 10-27. Настройка GPIFTool для временной диаграммы на рисунке 10-26

    Обычно при выполнении чтения FIFO для временной диаграммы требуется только одно "Активировать" (Activate), после чего каждое выполнение "Активировать" инкрементирует внутренний указатель FIFO (и EPxBCH:L) автоматически.

    Чтобы выполнить транзакцию чтения FIFO, необходимо:

  1. Установить бит RW в регистре GPIFTRIG и загрузить в EP1:0 соответствующую величину для FIFO, которое будет принимать данные.
  2. Запрограммировать FX2 на обнаружение выполнения транзакции. Как и для всех транзакций GPIF, бит 7 регистра GPIFTRIG (бит DONE) сигнализирует о выполнении транзакции.
  3. Запрограммировать FX2 на передачу данных ("pass-on") в конечную точку. Данные могут быть переданы из 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; // , packet start of text msg
EP8FIFOBUF[ 7 ] = 0x03; // , packet end of text msg
SYNCDELAY;
EP8BCH = 0x00;
SYNCDELAY;
EP8BCL = 0x08; // pass buffer on to host
}
}
 ... ... ... ... ...

}

    Рисунок 10-31. Чтение FIFO при AUTOIN = 0, передача пакетов через EPxBCL


10.4.6. Доступ через встроенное ПО к пакетам IN, AUTOIN=1

    Единственное различие между автоматическим (AUTOIN=1) и ручным (AUTOIN=0) режимами для пакетов IN заключается всвойстве длины пакета (EPxAUTOINLENH/L).

Рисунок 10-32. 
Транзакция чтения FIFO GPIF, (AUTOIN=1)

    Рисунок 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

    Рисунок 10-34. Вмешательство встроенного ПО, AUTOIN = 0/1


10.4.7. Доступ через встроенное ПО к пакетам IN, AUTOIN = 0

    В ручном IN режиме (AUTOIN = 0) возможны следующие варианты встроенного ПО:

  1. Оно может передавать ("pass-on") пакет(ы), посланные от ведущего хосту, когда буфер доступен, записывая в регистр INPKTEND соответствующий номер EPx и SKIP=0 (см. рисунок 10-35).
  2. Оно может пропустить пакет, записав в INPKTEND SKIP=1. См. рисунок 10-36.
  3. Оно может генерировать или редактировать пакет (например, писать прямо в EPxFIFOBUF), а затем писать в EPxBCL. См. рисунок 10-37.
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; // , packet start of text msg
EP8FIFOBUF[ 1 ] = 0x06; // 
EP8FIFOBUF[ 2 ] = 0x07; // 
EP8FIFOBUF[ 3 ] = 0x03; // , packet end of text msg
SYNCDELAY;
EP8BCH = 0x00;
SYNCDELAY;
EP8BCL = 0x04; // pass src'd buffer on to host
}
else
{
history_record( EP8, BAD_MASTER );
}
}
 ... ... ... ... ...

    Рисунок 10-37. Создание пакета IN при помощи записи в EPxBCH:L


10.4.7.1. Выполнение транзакции записи в FIFO

Рисунок 10-38. 
Встроенное ПО запускает временную диаграмму записи в FIFO

    Рисунок 10-38. Встроенное ПО запускает временную диаграмму записи в FIFO

Рисунок 10-39. 
Пример транзакции записи в FIFO

    Рисунок 10-39. Пример транзакции записи в FIFO

Рисунок 10-40. 
Временная диаграмма транзакции записи в FIFO.

    Рисунок 10-40. Временная диаграмма транзакции записи в FIFO.

    Показанная выше временная диаграмма выполняется до опустошения счётчика транзакций (в этом примере - когда он отсчитает 512). Счётчик транзакций декрементируется и опрашивается на каждом проходе через состояние ожидания.

    При каждом повторе временной диаграммы значение данных из FIFO выставляется на шину данных FIFO, а затем декрементируется и проверяется счётчик транзакций. Когда он опустошается, бит DONE устанавливается в 1 и генерируется запрос прерывания GPIFDONE.

Рисунок 10-41. 
Настройка GPIFTool для временной диаграммы на рисунке 10-40

    Рисунок 10-41. Настройка GPIFTool для временной диаграммы на рисунке 10-40

    Обычно при выполнении записи в FIFO для временной диаграммы достаточно только одного "NextData", после чего каждое выполнение "NextData" инкрементирует указатель FIFO.

    Чтобы выполнить транзакцию записи в FIFO, необходимо:

  1. Сбросить бит RW в регистре GPIFTRIG и загрузить в EP1:0 соответствующее значение для FIFO, который будет принимать данные.
  2. Запрограммировать FX2 на обнаружение выполнения транзакции. Как и для всех транзакций GPIF, бит 7 регистра GPIFTRIG (бит DONE) сообщает о завершении транзакции.
  3. Запрограммировать FX2 на передачу данных ("pass-on") из конечной точки в 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


10.4.8. Доступ через встроенное ПО к пакетам OUT, AUTOOUT = 1

    Для получения максимальной полосы пропускания хост и ведущий соединяются напрямую, когда AUTOOUT = 1. Данные из OUT FIFO в обход процессора автоматически передаются в хост.

Рисунок 10-45. Поток 
данных идёт мимо процессора, AUTOOUT = 1

    Рисунок 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.4.9. Доступ через встроенное ПО к пакетам OUT, AUTOOUT = 0

Рисунок 10-48. 
Встроенное ПО может пропускать или передавать данные

    Рисунок 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) возможны следующие варианты встроенного ПО:

  1. Оно может передавать ("pass-on") пакет(ы), посланные от хоста ведущему, когда буфер доступен, записывая 0 в бит SKIP регистра OUTPKTEND (OUTPKTEND.7) (см. рисунок 10-50):
    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

  2. Оно может пропускать пакет(ы), посланные от хоста ведущему, устанавливая бит SKIP в регистре EPxBCL (EPxBCL.7) (см. риунок 10-51).
    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

  3. Оно может редактировать пакет (или генерировать целиком пакет OUT) путём непосредственной записи в буфер FIFO и записывая затем длину пакета в EPxBCH:L. Запись в EPxBCL передаёт отредактированный пакет, поэтому запись в EPxBCL должна производиться после записи в EPxBCH (рисунок 10-52).
  4.     Во всех случаях буфер 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 очищен после сброса по включению питания


10.4.10. Пакетные (burst) транзакции 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; // , packet start of text msg
EP8FIFOBUF[ 7 ] = 0x03; // , packet end of text msg
SYNCDELAY;
EP8BCH = 0x00;
SYNCDELAY;
EP8BCL = 0x08; // pass buffer on to host
}
}

// 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-57. Пример пакетной транзакции чтения FIFO, запись в EPxBCL для передачи





10.5. Интерфейс UDMA


    Специально для реализации интерфейса UDMA (Ultra-ATA) в FX2 имеются дополнительные регистры. За более подробной информацией обращайтесь, пожалуйста, в Cypress Semiconductor Applications Department.




    На главную страницу

    К оглавлению

    Наверх



Hosted by uCoz