Программирование Файловые системы RAM Disk PID для службы файловой системы ADI FSS Tue, February 21 2017  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

RAM Disk PID для службы файловой системы ADI FSS Печать
Добавил(а) microsin   

В этом документе описана функциональность драйвера физического интерфейса диска (physical interface driver, сокращенно PID), носителем которого является оперативная память, ОЗУ (RAM Disk). Этот драйвер придерживается модели файловой системы компании Analog Devices (File System Service, ADI FSS), и предоставляет доступ к физическим устройствам с памятью на основе RAM. Из коробки доступна поддержка для всех процессоров Blackfin, которые поддерживаются библиотеками системных служб и драйверов устройств (System Services & Device Driver Library, сокращенно SSL и DDL). RAM Disk PID также может использоваться как конфигурируемая альтернатива встроенного RAM-диска, предоставляемого вместе с классом драйвера USB mass storage.

[Быстрый старт]

В этой секции предоставлена информация для быстрого запуска драйвера RAM Disk PID с использованием опций конфигурации по умолчанию. В таблице ниже перечислены ресурсы системных служб и драйверов, которые требуется установить в заголовочном файле adi_ssl_init.h. Они включают требования для ниже лежащих драйверов.

Таблица 1. Требования к ресурсам библиотек SSL и DDL.

Каналы DMA 0
Драйверы устройств 1
Семафоры 2
Callback-и флагов нет
Прерывания нет

Назначение памяти для RAM-диска. Поскольку минимально допустимый размер RAM-диска составляет порядка мегабайт, то для него можно использовать только внешнюю память Level 3 (SDRAM, L3). Один из вариантов реализовать это - назначить системную кучу (system heap) на память L3, и просто выделить требуемый размер с помощью стандартной функции malloc(), например:

u8 *pRamDiskFrame = (u8*)malloc(nRamDiskSize*512);

Здесь nRamDiskSize определено в секторах по 512 байт.

Альтернативно целые страницы памяти можно назначить с использованием оператора RESERVE в секцию, в секции файла LDF, изменяемую пользователем. Например, следующий пример предоставляет достаточное количество памяти в банке 2 для RAM-диска на 8 мегабайт:

RESERVE(RamDiskHeap=0x02800000, RamDiskHeap_length=8M)

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

extern "asm" int RamDiskHeap;
extern "asm" int RamDiskHeap_length;

И затем назначьте локальным переменным, глобально или в теле функции:

u8 *pRamDiskFrame = (u8*)&RamDiskHeap;
u32 nRamDiskSize  = (u32)&RamDiskHeap_length/512;

Подготовка к использованию совместно с FSS. Поскольку конфигурацию по умолчанию RAM-диска определить нельзя, заголовочный файл не предоставляет экземпляр ADI_FSS_DEVICE_DEF для этого драйвера. Вместо этого приложение должно определить его самостоятельно до выдачи команды ADI_FSS_CMD_ADD_DRIVER функции adi_fss_Init(), или передать его через вызов adi_fss_RegisterDevice().

В любом случае нужно послать следующие команды управления драйверу устройства после того, как он был открыт вызовом adi_dev_Open():

ADI_RAMDISK_CMD_SET_RAMDISK_START_LOCATION. Задает начальный адрес используемой памяти для носителя диска.

ADI_RAMDISK_CMD_SET_SIZE. Задает размер RAM-диска в секторах по 512 байт.

Если используется команда ADI_FSS_CMD_ADD_DRIVER, то эти команды должны быть добавлены в таблице конфигурации, назначенной полем pConfigTable структуры ADI_FSS_DEVICE_DEF. Если драйвер открывается вне FSS – с использованием вызова adi_fss_RegisterDevice() – то необходимо добавить также выполнение следующей команды:

{ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *)ADI_DEV_MODE_CHAINED}

Использование adi_fss_RegisterDevice() описано ниже, в разделе "Регистрация RAM Disk PID со службой FSS". Структура ADI_FSS_DEVICE_DEF (описана в секции "ADI_FSS_DEVICE_DEF", где описана структура определения устройства) заполняется следующими значениями:

DeviceNumber 0
pEntryPoint &ADI_RAMDISK_Entrypoint
pConfigTable Указатель на таблицу конфигурации, как описано выше.
pCriticalRegionData NULL
Direction ADI_DEV_DIRECTION_BIDIRECTIONAL
DeviceHandle Место для сохранения хендла экземпляра драйвера RAM-диска.
DefaultMountPoint Значение ADI_FSS_VOLUME_IDENT, которое то же самое, что и одиночный символ, например 'r'. Можно указать значение 0, чтобы автоматически присвоить следующую свободную букву диска.

Однако FSS не сможет получить доступ к файловой системе на носителе RAM-диска, поскольку данные на нем пока не содержат ни таблицу разделов, ни FAT. Исключением из этого случая может быть ситуация, когда RAM-диск уже отформатирован предыдущим включением системы (если обеспечена сохранность файловой системы между её перезагрузками, либо между выключением и включением питания). В следующей разделе описывается форматирование RAM-диска.

Форматирование RAM-диска. Перед тем, как RAM-диск сможет использовать FSS, его нужно отформатировать. Чтобы выполнить это, требуется явное открытие и конфигурирование PID, создание экземпляра драйвера FAT. Чтобы упростить эту процедуру, RAM Disk PID API представляет специальную функцию, ConfigRamDiskFssDeviceDef(), которая открывает, конфигурирует и форматирует RAM-диск. Эта функция вернет хендл на адекватно сформированную структуру ADI_FSS_DEVICE_DEF, которую потом нужно передать функции adi_fss_RegisterDevice() (для регистрации устройства драйвера с файловой системой FSS). Поскольку RAM-диски скорее всего будут намного меньше максимально допустимого размера для FAT16 (2 гигабайта), эта функция форматирует RAM как FAT16 с меткой тома FAT16RAM. Минимальный форматируемый размер RAM-диска составляет 4.1 мегабайт (4200 секторов). Используется обычный размер сектора 512 байт. Ниже приведен прототип функции ConfigRamDiskFssDeviceDef():

ADI_FSS_DEVICE_DEF *ConfigRamDiskFssDeviceDef (u8 *pRamDiskFrame,
                                               u32 nRamDiskSize,
                                               ADI_DEV_MANAGER_HANDLE hDevMgrHandle,
                                               ADI_DCB_HANDLE hDcbHandle,
                                               u32 nUsbDelay);

Аргументы этой функции представлены в следующей таблице:

pRamDiskFrame Указатель на память ОЗУ, которая используется как носитель данных для RAM-диска.
nRamDiskSize Размер носителя данных RAM-диска в секторах по 512 байт, минимально допустимое значение 4200.
hDevMgrHandle Хендл Менеджера Устройств - не может быть NULL.
hDcbHandle Хендл Менеджера DCB (отложенный запуск функций обратного вызова) - может быть NULL.
nUsbDelay Задержка в микросекундах, предназначенная для совместной работы с драйвером USB MSD. См. определение команды ADI_RAMDISK_CMD_SET_USB_DELAY.
DeviceHandle Место для сохранения хендла экземпляра драйвера RAM-диска.
DefaultMountPoint Значение ADI_FSS_VOLUME_IDENT, которое то же самое, что и одиночный символ, например 'r'. Можно указать значение 0, чтобы автоматически присвоить следующую свободную букву диска.

Функция создаст временный экземпляр драйвера FAT с использованием минимальных размеров кеша сектора FAT и кеша кластера записи директории - соответственно 4 сектора и 2 кластера.

После вызова функции ConfigRamDiskFssDeviceDef можно вызвать либо функцию adi_fss_RegisterDevice(), чтобы зарегистрировать устройство для FSS, либо драйвер может быть закрыт, и структура ADI_FSS_DEVICE_DEF передана в функцию adi_fss_Init(). В последнем случае структура ADI_FSS_DEVICE_DEF должна быть заполнена так же, как было показано выше (в вызове ConfigRamDiskFssDeviceDef() назначаются только поля Direction, DeviceHandle и DefaultMountPoint).

Как использовать функции ConfigRamDiskFssDeviceDef() и adi_fss_RegisterDevice(), см. пример приложения shell_browser для платы разработчика ADSP-BF533 EZ-KIT и аналогичные примеры (поставляются вместе с VisualDSP++ 5.0).

Требования к динамически выделяемой памяти. В следующей таблице показано количество необходимой выделяемой памяти. Подробнее про работу с кучами, чтобы назначать области памяти для PID, см. описание FSS в руководстве "Device Drivers and System Services Manual for Blackfin® Processors" (перевод см. в [2]), а также статьи [3,4].

Операция Тип кеша FSS Размер (в байтах)
Экземпляр драйвера Общая куча (General Heap) 88
Всего 88

[Файлы ADI RAM Disk PID]

Файлы драйвера находятся в каталоге установки системы программирования VisualDSP++ 5.0, обычно это папка c:\Program Files (x86)\Analog Devices\VisualDSP 5.0\Blackfin\.

Заголовочный файл. Исходный код драйвера и модули пользователя подключают файл include\drivers\pid\ramdisk\adi_ramdisk.h. В нем содержатся все определения, прототипы функций и т. п., специфические для RAM Disk PID.

Исходный код. Весь код драйвера содержится в файле lib\src\drivers\pid\ramdiskadi_ramdisk.c, он написан на языке C. Никакие функции на ассемблере не используются. Драйвер RAM Disk PID не использует никакие нижележащие драйверы.

Документация. Описание драйвера на английском языке находится в файле docs\drivers\pid\ramdisk\adi_ramdisk.pdf.

[Требуемые ресурсы]

Драйверы устройств обычно потребляют некоторое количество системных ресурсов. В этом разделе описаны ресурсы, требуемые для драйвера устройства RAM Disk PID.

Память. Все требования к памяти, отличающиеся от структур данных, создаваемых в стеке, удовлетворяются через вызовы централизованных функций управления памяти FSS: _adi_fss_malloc(), _adi_fss_realloc() и _adi_fss_free(). Это обертки либо для функций по умолчанию libc (это heap_malloc(), heap_realloc() и heap_free()), либо функций, специфических для приложения, предоставленных при конфигурировании FSS (см. команды ADI_FSS_CMD_SET_CACHE_HEAP_ID, ADI_FSS_CMD_SET_GENERAL_HEAP_ID, ADI_FSS_CMD_SET_MALLOC_FUNC, ADI_FSS_CMD_SET_REALLOC_FUNC, ADI_FSS_CMD_SET_FREE_FUNC [5]). В последнем случае разработчик может выбрать собственные функции управления памятью, например он может предоставлять фиксировано организованные области памяти.

Службой FSS поддерживается 2 типа куч, куча для кеша (cache heap), применяемая для буферов данных, таких как источник и цель передач DMA, и куча общего назначения (general heap, обычно она соответствует SRAM L1), чтобы размещать в ней данные наподобие экземпляров структур. Драйвер RAM Disk PID использует кучу общего назначения так же, как это определено для FSS - только для хранения поддерживаемых информационных структур. Куча кеша не требуется.

Выше в таблице 1 были даны требования к объему динамически выделяемой памяти.

Прерывания. Драйвер RAM Disk PID не использует никакие прерывания.

DMA. Драйвер RAM Disk PID не использует никакие каналы прямого доступа к памяти (DMA).

Семафоры. Драйвер RAM Disk PID требует выделения памяти только для 2 семафоров, один для предоставления исключительного доступа, и другой для обслуживания передач данных.

Таймеры. Драйвер RAM Disk PID не использует службу таймеров.

Часы реального времени. Драйвер RAM Disk PID не использует службу Real-Time Clock (RTC).

Программируемые флаги. Программируемые флаги также не используются RAM Disk PID.

Выводы процессора. Выводы процессора также не используются RAM Disk PID.

[Поддерживаемые функции драйвера устройства]

Направление данных. Поддерживается только один вариант направления данных - двунаправленный, ADI_DEV_DIRECTION_BIDIRECTIONAL. Таким образом, устройство драйвера может как передавать, так и принимать данные.

Метод потока. RAM Disk PID может поддерживать только метод потока ADI_DEV_MODE_CHAINED. Когда драйвер используется совместно с FSS, это применяется автоматически. Если драйвер RAM Disk PID используется самостоятельно, или открывается перед регистрацией совместно с FSS, то важно послать драйверу следующую пару команда-значение:

{ ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void*)ADI_DEV_MODE_CHAINED },

Типы буферов. Драйвер RAM Disk PID поддерживает только линейные одномерные буферы ADI_DEV_1D_BUFFER. Вот описание используемых полей структуры такого буфера:

CallbackParameter. Здесь содержится адрес структуры супербуфера.
ProcessedFlag. Это поле не используется в RAM Disk PID.
pAdditionalInfo. Это поле не используется в RAM Disk PID.

Буфер ADI_DEV_1D_BUFFER окружен структурой супербуфера FSS (см. секцию "ADI_FSS_SUPER_BUFFER" с описанием структуры супербуфера FSS).

Идентификаторы команд. В этой секции перечислены команды, которые поддерживаются/требуется драйвером RAM Disk PID. Эти команды поделены на 3 секции. Первая врезка описывает команды, которые поддерживаются напрямую Менеджером Устройств (Device Manager). Вторая врезка описывает общие команды драйвера устройства, которые поддерживает RAM Disk PID. Эти команды поддерживают все драйверы PID. И последняя, третья врезка описывает команды, специфичные именно для драйвера RAM Disk PID.

Команды передаются драйверу через функцию adi_dev_Control(). Функция adi_dev_Control() принимает 3 аргумента:

DeviceHandle. Этот параметр имеет тип ADI_DEV_DEVICE_HANDLE, который уникально идентифицирует драйвер устройства. Этот хендл предоставляется клиенту как результат работы вызова функции adi_dev_Open().
CommandID. Этот параметр типа u32, он задает идентификатор команды.
Value. Этот параметр типа void *, и его значение зависит от контекста, т. е. используемой команды.

Во врезках ниже перечислены идентификаторы команд, поддерживаемые драйвером, и описание соответствующих значений Value для каждого идентификатора команды CommandID.

Команды, перечисленные ниже, поддерживаются и обрабатываются напрямую Менеджером Устройств (Device Manager). Здесь описаны только те команды, которые имеют отношение к RAM Disk PID.

ADI_DEV_CMD_TABLE. Задает таблицу пар команда-значение, передаваемых драйверу. Параметр Value определяет адрес таблицы (ADI_DEV_CMD_VALUE_PAIR *).

ADI_DEV_CMD_END. Обозначает конец таблицы команд. Параметр Value игнорируется (может быть равен NULL).

ADI_DEV_CMD_PAIR. Передает одну пару команда-значение. Параметр Value определяет адрес этой пары (ADI_DEV_CMD_VALUE_PAIR *).

ADI_DEV_CMD_SET_DATAFLOW_METHOD. Задает метод потока данных. Как уже упоминалось, поддерживается только один метод потока данных: ADI_DEV_MODE_CHAINED. Value: значение из перечисления ADI_DEV_MODE (поддерживается только значение ADI_DEV_MODE_CHAINED).

ADI_DEV_CMD_GET_PERIPHERAL_DMA_SUPPORT. Позволяет определить, поддерживает ли драйвер устройства периферийный DMA. Value типа u32 * (ячейка, где будет сохранено значение TRUE или FALSE). RAM Disk PID всегда вернет false.

ADI_DEV_CMD_SET_DATAFLOW. Разрешает/запрещает поток данных через устройство. Value – TRUE/FALSE.

Команды, перечисленные ниже, будут поддержаны и обработаны RAM Disk PID. Идентификаторы этих команд уникальны для FSS.

ADI_FSS_CMD_GET_BACKGRND_XFER_SUPPORT. Запрашивает RAM Disk PID вернуть TRUE или FALSE, в зависимости от того, поддерживает ли устройство фоновую передачу данных. Имя этой команды может ввести в заблуждение, так как её главное назначение - определить, можно ли эффективно использовать кеш FSS, или нет. RAM Disk PID в настоящее время возвращает TRUE, так как использование файлового кеша может быть выгодным даже на таком быстром носителе, как SDRAM. Value – место в памяти, предоставленное клиентом, чтобы команда возвратила туда результат.

ADI_FSS_CMD_GET_DATA_ELEMENT_WIDTH. Запрашивает RAM Disk PID вернуть ширину (в байтах) для каждого элемента данных. RAM Disk PID всегда возвращает значение 4. Value – место в памяти, предоставленное клиентом, чтобы команда возвратила туда результат.

ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE. Запрашивает RAM Disk PID предоставить семафор блокировки (Lock Semaphore), чтобы вызывающий модуль получил исключительный доступ к функциям передачи данных PID. Value – NULL.

ADI_FSS_CMD_RELEASE_LOCK_SEMAPHORE. Запрашивает PID освободить семафор блокировки (Lock Semaphore), предоставленный в ответ на команду ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE. Value – NULL.

ADI_FSS_CMD_SET_CACHE_HEAP_ID. Инструктирует экземпляр RAM Disk PID использовать указанный индекс кучи для динамического выделения буферов данных. Индекс по умолчанию для кучи равен -1, показывая тем самым, что должна использоваться общая куча файловой системы (FSS General Heap). Value – индекс требуемой кучи.

ADI_PID_CMD_GET_FIXED. Запрашивает RAM Disk PID возвратить TRUE или FALSE в зависимости от того, может ли считаться устройство фиксированным, или же оно извлекаемое. RAM Disk PID возвращает FALSE. Value – место в памяти, предоставленное клиентом, чтобы команда возвратила туда результат.

ADI_PID_CMD_MEDIA_ACTIVATE. Активирует RAM Disk PID, конфигурируя его для использования. Value – TRUE для активации, FALSE для деактивации.

ADI_DEV_CMD_GET_INBOUND_DMA_PMAP_ID. Вернет привязку периферийного устройства (PMAP ID) для входящего канала DMA драйвера устройства. Эта команда важна для драйверов PID, основанных на DMA. Value: u32* (указывает на ячейку памяти, куда будет сохранено значение привязки PMAP).

ADI_PID_CMD_POLL_MEDIA_CHANGE. Инструктирует RAM Disk PID проверить состояние устройства на предмет извлечения или установки носителя данных. Если драйвер детектировал, что носитель был извлечен, то он выдает callback-событие ADI_FSS_EVENT_MEDIA_REMOVED для callback-функции Device Manager. Если драйвер детектирует, что носитель был установлен, то он выдает callback-событие ADI_FSS_EVENT_MEDIA_INSERTED (см. ниже раздел "События Callback"). Value – NULL.

ADI_PID_CMD_DETECT_VOLUMES. Инструктирует RAM Disk PID распознать тома/разделы на носителе данных. Для каждого детектированного тома PID выдает событие ADI_FSS_EVENT_VOLUME_DETECTED, передавая указатель на относящуюся к тому информацию в качестве третьего аргумента (см. ниже раздел "События Callback"). Value – NULL.

ADI_PID_CMD_GET_MAX_TFRCOUNT. Запрашивает максимальный размер в байтах для одиночной передачи (запрос LBA). RAM Disk PID ограничен только размером поля ElementCount структуры ADI_DEV_1D_BUFFER, которое декларировано как u32, и всегда вернет значение 0xFFFFFFFF. Value – место в памяти, предоставленное клиентом, чтобы команда возвратила туда результат.

ADI_PID_CMD_SEND_LBA_REQUEST. Запрашивает RAM Disk PID подать команду устройству, чтобы прочитать/записать некоторое количество секторов из устройства/в устройство по указанному начальному сектору LBA (LBA start sector). Value – адрес структуры ADI_FSS_LBA_REQUEST, содержащей вышеперечисленную информацию. Это игнорируется драйвером RAM Disk PID, поскольку информация LBA передается драйверу как часть структуры супербуфера ADI_FSS_SUPER_BUFFER, переданной функциям adi_dev_Read/Write().

ADI_PID_CMD_ENABLE_DATAFLOW. Инструктирует RAM Disk PID предпринять необходимые шаги для начала/остановки потока данных. Это игнорируется драйвером RAM Disk PID, поскольку все передачи данных завершены при возврате из функций adi_dev_Read/Write(). Value - TRUE/FALSE.

ADI_PID_CMD_SET_DIRECT_CALLBACK. Предоставляет адрес callback-функции, чтобы она вызывалась напрямую (без откладывания на уровень кода вне прерываний, т. е. без использования Менеджера DCB) при событиях установки/извлечения носителя и событиях детектирования тома (см. ниже раздел "События Callback"). Value – адрес callback-функции.

ADI_PID_CMD_GET_GLOBAL_MEDIA_DEF. Запрашивает RAM Disk PID для возврата информации, относящейся к общей геометрии установленного устройства. Value – адрес структуры ADI_FSS_VOLUME_DEF для сохранения всей информации об устройстве. Ниже перечислены поля этой структуры ADI_FSS_VOLUME_DEF:

FileSystemType. Не используется.
StartAddress. Сектор (значение LBA) первого сектора на носителе, который можно использовать.
VolumeSize. Общее количество секторов на устройстве.
SectorSize. Размер в байтах каждого сектора.

Значения по умолчанию для RAM Disk PID - размер сектора 512 байт, начиная с логического сектора 0.

Идентификаторы команд, перечисленные ниже, уникальны для RAM Disk PID.

ADI_RAMDISK_CMD_SET_RAMDISK_START_LOCATION. Определяет область памяти, которую использует RAM Disk под носитель данных. Value – адрес начала области памяти L3, которая отведена под RAM disk. Значение по умолчанию не предоставлено, т. е. выдача этой команды обязательна.

ADI_RAMDISK_CMD_SET_SIZE. Определяет размер носителя RAM Disk. Value - размер в секторах по 512 байт. Значение по умолчанию не предоставлено, т. е. выдача этой команды обязательна.

ADI_RAMDISK_CMD_SET_USB_DELAY. Устанавливает задержку в микросекундах, которая вставляется после завершения каждой передачи. Это иногда требуется, чтобы этот драйвер можно было использовать совместно с классом устройств USB MSC. Value – задержка в микросекундах, значение по умолчанию - 0.

[События Callback]

В этой секции перечислены события callback, которые генерирует RAM Disk PID. Эти события детализированы в 2 секциях. Первая секция описывает события, которые являются общими для многих драйверов устройств. Следующая секция описывает события, относящиеся к специфическим для FSS идентификаторам событий. FSS определяет callback-функцию, которая поддерживает требуемые события (Events). Для отдельного использования (без FSS) разработчик должен подготовить callback-функцию, чтобы обработать каждое событие, описанное в этих двух секциях.

Callback-функция имеет тип ADI_DCB_CALLBACK_FN, и она получает 3 параметра:

ClientHandle. Исключая callback-и прямого вызова, это параметр void*, который будет DeviceHandle, 3-й аргумент, переданный в функцию adi_pdd_Open драйвера PID. Для callback-ов прямого вызова это должен быть адрес этого аргумента.
EventID. Значение типа u32, которое указывает идентификатор события (event ID). См. ниже определение идентификаторов событий.
Value. Это параметр типа void*, значение которого зависит от контекста, т. е. от event ID.

Большинство callback-ов направляется в вызов callback-функции, предоставленной Менеджером Устройств (Device Manager) как третий аргумент DMCallback, переданный в функцию adi_pdd_Open драйвера PID. Device Manager будет выставлять отложенный вызов callback-функции (deferred callback), если в adi_dev_Open() был передан допустимый хендл очереди функций обратного вызова (так называемый хендл Менеджера DCB). Поддержка функций отложенного вызова (deferred callback) управляется конфигурацией FSS (File System Service, служба файловой системы).

Исключение из этого правила - события ADI_FSS_EVENT_MEDIA_INSERTED, ADI_FSS_EVENT_MEDIA_REMOVED и ADI_FSS_EVENT_VOLUME_DETECTED, где в контексте службы файловой системы (FSS) должны использоваться прямые вызовы функций callback (non-deferred callback, т. е. без Менеджера DCB). Эти функции для прямого вызова устанавливаются FSS командой ADI_PID_CMD_SET_DIRECT_CALLBACK. Пожалуйста обратите внимание, что в этом случае ClientHandle для передачи в callback-функцию это адрес аргумента DeviceHandle.

Для отдельного использования (без FSS), когда команда ADI_PID_CMD_SET_DIRECT_CALLBACK опущена, RAM Disk PID будет использовать обычный маршрут вызовов Device Manager.

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

События в этой секции относятся к многим драйверам устройств. В настоящее время RAM Disk PID генерирует только одно подобное общее событие.

ADI_DEV_EVENT_BUFFER_PROCESSED. Оповещает callback-функцию, что буфер ввода/вывода в цепочке буферов обработан драйвером устройства (драйвер RAM Disk PID поддерживает только один тип одномерных, цепочечных буферов adi_dev_1d_buffer, который устанавливается командой ADI_DEV_MODE_CHAINED). Value – это значение параметра CallbackParameter, которое предоставляется в буфере, который был передан в функцию adi_dev_Read() или adi_dev_Write(). Для совместимости с требованиями FSS это значение будет адресом буфера adi_dev_1d_buffer.

События, перечисленные ниже, поддерживаются и обрабатываются драйвером RAM Disk PID. Эти идентификаторы уникальны для этого драйвера устройства.

ADI_FSS_EVENT_MEDIA_INSERTED. Это событие выдается в ответ на команду ADI_PID_CMD_POLL_MEDIA_CHANGE, когда детектировано наличие носителя, и когда детектирована допустимая лицензия FTL. Value – адрес места размещения данных. При выдаче callback это место содержит номер устройства (Device Number), равный 0. При возврате из callback это место содержит код результата. Если код возвращенного результата ADI_FSS_RESULT_SUCCESS, то RAM Disk PID будет рассматривать, что носитель существует, и он корректно распознан FSS.

ADI_FSS_EVENT_VOLUME_DETECTED. Это событие выдается в ответ на команду ADI_PID_CMD_DETECT_VOLUMES, когда был детектирован допустимый том/раздел. Value – адрес структуры ADI_FSS_VOLUME_DEF, определяющей том. Вот её поля:

FileSystemType. Тип файловой системы, как это определено в заголовочном файле adi_fss.h под заголовком "Enumerator for known File System types" (известные, поддерживаемые типы файловых систем. В настоящее время поддерживается только FAT). Подробнее см. документацию, касающуюся реализации FSS [5].
StartAddress. Сектор (значение LBA) первого сектора тома. Для RAM Disk PID это будет всегда 0.
VolumeSize. Размер тома в секторах.
SectorSize. Это размер каждого сектора тома в байтах. Значение по умолчанию 512 байт.
DeviceNumber. Номер устройства в цепочке устройств. Это поле не применимо в данном контексте и всегда установлено в 0.

Эта структура должна обрабатываться FSS (либо callback-функцией приложения, когда драйвер используется без FSS) как volatile, так что она может быть декларирована в стеке RAM Disk PID. Эти значения копируются в FSS или callback-функции перед возвратом управления в RAM Disk PID, если они должны быть сохранены.

ADI_PID_EVENT_DEVICE_INTERRUPT. Это событие выдается RAM Disk PID всякий раз, когда обработаны данные, содержащиеся в запросе LBA. Value – адрес структуры буфера, связанного с этим событием. Это должно быть значение, находящееся в поле pBuffer связанной структуры запроса LBA.

[Коды возврата]

Все API-функции RAM Disk PID возвратят код состояния, показывающий либо успешное завершение функции драйвера, либо ошибку, которая произошла в процессе выполнения функции. В этой секции перечислены коды возврата, которые драйвер устройства может возвратить клиенту. Возвращаемое значение ADI_DEV_RESULT_SUCCESS или ADI_FSS_RESULT_SUCCESS (оба этих кода всегда равны 0) показывают успех, в то время как любое другое значение (оно всегда не нулевое) показывает ошибку или какой-то другой информативный результат.

Коды возврата поделены на 2 секции. Первая описывает коды возврата, которые являются общими для многих драйверов устройства. Следующая секция описывает коды возврата, относящиеся именно к этому драйверу. Клиент должен подготовить обработку каждого из кодов, описанных в этих двух секциях.

Обычно приложение должно проверить код возврата на равенство ADI_DEV_RESULT_SUCCESS, и предпринять соответствующие корректирующие действия, когда не был возвращен код ADI_DEV_RESULT_SUCCESS (обработать ошибку). Например:

if (adi_dev_Xxxx(...) == ADI_DEV_RESULT_SUCCESS)
{
   // Нормальная обработка, ошибки нет:
   ...
}
else
{
   // Обработка ошибки:
   ...
}

Коды возврата, описанные в этой врезке, являются общими для многих драйверов устройств. Этот список перечисляет все общие коды, которые поддерживаются драйвером RAM Disk PID.

ADI_DEV_RESULT_SUCCESS. Функция завершилась успешно.

ADI_DEV_RESULT_NOT_SUPPORTED. Эта функция не поддерживается драйвером.

ADI_DEV_RESULT_DEVICE_IN_USE. Устройство уже используется.

ADI_DEV_RESULT_NO_MEMORY. Недостаточно памяти.

ADI_DEV_RESULT_BAD_DEVICE_NUMBER. Недопустимый номер устройства.

ADI_DEV_RESULT_DIRECTION_NOT_SUPPORTED. Устройство не может быть открыто в указанном направлении передачи данных.

ADI_DEV_RESULT_BAD_DEVICE_HANDLE. Недопустимый хендл драйвера устройства.

ADI_DEV_RESULT_BAD_MANAGER_HANDLE. Недопустимый хендл Менеджера Устройств.

ADI_DEV_RESULT_BAD_PDD_HANDLE. Недопустимый хендл физического драйвера.

ADI_DEV_RESULT_INVALID_SEQUENCE. Запрошенное действие не находится в допустимой последовательности.

ADI_DEV_RESULT_ATTEMPTED_READ_ON_OUTBOUND_DEVICE. Клиент (вызывающий код) попытался предоставить входящий буфер для устройства, которое было открыто только для исходящего трафика.

ADI_DEV_RESULT_ATTEMPTED_WRITE_ON_INBOUND_DEVICE. Клиент попытался предоставить исходящий буфер для устройства, которое было открыто только для входящего трафика.

ADI_DEV_RESULT_DATAFLOW_UNDEFINED. Метод подтока еще не был декларирован.

ADI_DEV_RESULT_DATAFLOW_INCOMPATIBLE. Метод потока несовместим с запрошенным действием.

ADI_DEV_RESULT_BUFFER_TYPE_INCOMPATIBLE. Устройство не поддерживает предоставленный тип буфера.

ADI_DEV_RESULT_NON_TERMINATED_LIST. Предоставленная цепочка буферов не завершена NULL.

ADI_DEV_RESULT_NO_CALLBACK_FUNCTION_SUPPLIED. Требуется callback-функция, но она не была предоставлена.

ADI_DEV_RESULT_REQUIRES_BIDIRECTIONAL_DEVICE. Требуется устройство, открытое только для двунаправленного трафика.

Следующие коды возврата определены в заголовочном файле < services/fss/adi_fss.h >:

ADI_FSS_RESULT_NO_MEDIA. Не был детектирован носитель, либо не была детектирована допустимая лицензия FTL.

ADI_FSS_RESULT_NO_MEMORY. Недостаточно памяти для выполнения запроса. Обычно происходит в результате неудачного вызова _adi_fss_malloc().

ADI_FSS_RESULT_FAILED. Общая ошибка.

ADI_FSS_RESULT_NOT_SUPPORTED. Запрошенная операция не поддерживается PID.

ADI_FSS_RESULT_SUCCESS. Общий код успешного завершения.

[Структуры данных]

ADI_DEV_PDD_ENTRY_POINT. Это так называемая структура точек входа в драйвер (Device Driver Entry Points). Эта структура используется в общем для всех драйверов, удовлетворяющих модели драйверов устройств Analog Devices (ADI Device Driver model), и она содержит адреса стандартного набора функций драйвера устройства. Эта структура определена в модуле исходного кода RAM Disk PID, файл adi_ramdisk.c, и декларирована как переменная extern в заголовочном файле RAM Disk PID, adi_ramdisk.h:

extern ADI_DEV_PDD_ENTRY_POINT ADI_RAMDISK_Entrypoint;

ADI_DEV_CMD_VALUE_PAIR. Это структура для определения пары команда-значение, используемая всеми драйверами устройств, удовлетворяющих модели драйверов устройств Analog Devices (ADI Device Driver model). Структура используется в основном для начальной конфигурации драйвера. Драйвер RAM Disk PID должен поддерживать все 3 метода передачи пар команда-значение:

adi_dev_Control( ..., ADI_DEV_CMD_TABLE, (void*)< адрес таблицы пар команда-значение > );
adi_dev_Control( ..., ADI_DEV_CMD_PAIR, (void*)< адрес одной пары команда-значение > );
adi_dev_Control( ..., < команда >, (void*)< значение, связанное с командой > );

Таблица команд, применяемая по умолчанию для драйвера, определена в заголовочном файле RAM Disk PID, adi_ramdisk.h.

ADI_FSS_DEVICE_DEF. Это структура определения устройства, используемая для инструктирования FSS, как открыть и сконфигурировать RAM Disk PID. Содержимое этой структуры в основном это набор параметров, переданных как аргументы в вызов adi_dev_Open(). Структура определена в заголовочном файле службы файловой системы adi_fss.h следующим образом:

typedef struct
{
   u32 DeviceNumber;
   ADI_DEV_PDD_ENTRY_POINT *pEntryPoint;
   ADI_DEV_CMD_VALUE_PAIR *pConfigTable;
   void *pCriticalRegionData;
   ADI_DEV_DIRECTION Direction;
   ADI_DEV_DEVICE_HANDLE DeviceHandle;
   ADI_FSS_VOLUME_IDENT DefaultMountPoint;
} ADI_FSS_DEVICE_DEF;

Поля этой структуры назначаются, как показано в следующей таблице:

DeviceNumber Определяет, какое периферийное устройство используется. Применяется как аргумент DeviceNumber, требуемый для вызова adi_dev_Open(). Это значение игнорируется драйвером RAM Disk PID.
pEntryPoint Это указатель на точку входа в драйвер устройств (массив указателей на стандартные функции драйвера ADI). Передается как аргумент pEntryPoint, требуемый для вызова adi_dev_Open(). Для RAM Disk PID это значение назначается в &ADI_RAMDISK_EntryPoint.
pConfigTable Это указатель на таблицу пар команда-значение, чтобы конфигурировать RAM Disk PID. Для RAM Disk PID значение по умолчанию NULL.
pCriticalRegionData Это указатель на аргумент, который должен быть передан в функцию adi_int_EnterCriticalRegion() библиотеки системных служб (SSL). В настоящее время эта возможность не используется, и здесь должен быть NULL.
Direction Это аргумент Direction, требуемый для вызова функции adi_dev_Open(). Для драйвера RAM Disk PID это значение должно быть ADI_DEV_DIRECTION_BIDIRECTIONAL.
DeviceHandle Это указатель на место в памяти, используемой внутри драйвера. Здесь сохраняется хендл драйвера устройства - набор данных, полученный при возврате из вызова функции adi_dev_Open(). Перед инициализацией должно быть установлено в NULL.
DefaultMountPoint Это буква по умолчания, используемая для обслуживания диска под управлением RAM Disk PID. Установка этого поля гарантирует, что будет использоваться каждый раз одна и та же буква диска, когда монтируется RAM-диск. Определение по умолчанию в заголовочном файле adi_ramdisk.h оставляет это поле пустым.

Экземпляр по умолчанию этой структуры определена в заголовочном файле RAM Disk PID, adi_ramdisk.h, защищена от повторного подключения в исходном модуле PID, и будет доступна в модуле приложения только если разработчик определит в нем макрос _ADI_RAMDISK_DEFAULT_DEF_:

#if !defined(__ADI_RAMDISK_HOST_C__)
...
#if defined(_ADI_RAMDISK_DEFAULT_DEF_)
static ADI_FSS_DEVICE_DEF ADI_RAMDISK_Def = { ... };
...
#endif
...
#endif

ADI_FSS_VOLUME_DEF. Это структура определения тома, используемая в RAM Disk PID для обмена с FSS. В ней представлено описание тома, который можно использовать. Адрес глобального экземпляра этой структуры будет возвращен как третий аргумент callback-функции, посланный к FSS вместе с событием ADI_FSS_EVENT_VOLUME_DETECTED. Структура определена в заголовочном файле службы файловой системе adi_fss.h следующим образом:

typedef struct
{
   u32 FileSystemType;
   u32 StartAddress;
   u32 VolumeSize;
   u32 SectorSize;
   u32 DeviceNumber;
} ADI_FSS_VOLUME_DEF;

Поля этой структуры назначаются, как показано в следующей таблице:

FileSystemType Это уникальный идентификатор, определяющий тип файловой системы. Допустимые типы декларируются в анонимном перечислении заголовочного файла FSS. Для RAM Disk PID это значение всегда ADI_FSS_FSD_TYPE_FAT.
StartAddress Начальный сектор тома/раздела в формате LBA.
VolumeSize Количество секторов, содержащихся в томе/разделе.
SectorSize Количество байт на сектор, используемое в томе/разделе.
DeviceNumber Это используется для индикации номера устройства в цепочке устройств. Для RAM Disk PID всегда устанавливается в 0.

Служба файловой системы (FSS) рассматривает эту структуру как volatile, и будет делать копию ее содержимого.

ADI_FSS_SUPER_BUFFER. Это структура супербуфера FSS. Супербуфер используется как обертка над структурой буфера ADI_DEV_1D_BUFFER. По этой причине в структуре ADI_FSS_SUPER_BUFFER в качестве первого поля находится структура ADI_DEV_1D_BUFFER, так что эти две структуры имеют общий адрес. Это используется следующим образом:

• Адрес супербуфера может использоваться в вызовах adi_dev_Read/adi_dev_Write, и
• В коде этих функция может быть разименован указатель на супербуфер, и может быть получен доступ к его содержимому.

На каждой стадии процесса обработки, от файлового кеша FSD до PID, супербуфер получает на всем пути уместную информацию. Эти поля определенны в следующей таблице, и цветами помечены их разновидности. Красным помечены поля, относящиеся к файловому кешу, зеленым поля, устанавливаемые драйвером FSD, и синим поля, устанавливаемые драйвером PID. Запрос LBA устанавливается драйвером FSD для запросов, исходящих и от кеша, и от FSD, или в PID для его собственных внутренних запросов.

Имейте в виду, что для использования вне контекста службы файловой системы (FSS) все вызовы adi_dev_Read() или adi_dev_Write() с хендлом устройства RAM Disk PID должны использовать адрес допустимой структуры супербуфера ADI_FSS_SUPER_BUFFER.

Владелец супербуфера установит в 0 те его поля, которые не уместны. Определение структуры супербуфера следующее:

typedef struct ADI_FSS_SUPER_BUFFER
{
   ADI_DEV_1D_BUFFER Buffer;
   struct adi_cache_block *pBlock;
   u8 LastInProcessFlag;
   ADI_FSS_LBA_REQUEST LBARequest;
   ADI_SEM_HANDLE SemaphoreHandle;
   ADI_FSS_FILE_DESCRIPTOR *pFileDesc;
   ADI_DCB_CALLBACK_FN FSDCallbackFunction;
   void *FSDCallbackHandle;
   ADI_DCB_CALLBACK_FN PIDCallbackFunction;
   void *PIDCallbackHandle;
} ADI_FSS_SUPER_BUFFER;

Поля этой структуры определены следующим образом:

Buffer Структура ADI_DEV_BUFFER, требуемая для перемещения данных. Обратите внимание, что это не поле указателя. Это поле должно быть установлено драйвером RAM Disk PID только в том случае, когда он выдает запрос на передачу данных.
SemaphoreHandle Хендл семафора для публикации после завершения перемещения данных. Это должно быть установлено драйвером RAM Disk PID только в том случае, когда он выдает запрос передачи данных, и тогда сюда должно быть записано значение хендла семафора, сохранное в данных экземпляра драйвера RAM Disk PID. См. секции ниже для описания использования семафоров.
LBARequest Структура ADI_FSS_LBA_REQUEST для связанного буфера. Подробнее см. ниже описание этой структуры.
pBlock Используется в файловом кеше FSS. Это значение не должно изменяться драйвером RAM Disk PID. Для внутренних передач драйвера RAM Disk PID это должно быть установлено в NULL.
LastinProcessFlag
pFileDesc
FSDCallbackFunction Это поле зарезервировано для использования драйверами FSD. Для внутренних передач данных RAM Disk PID должно быть установлено в NULL.
FSDCallbackHandle
PIDCallbackFunction RAM Disk PID назначает адрес callback-функции, которая запускается при событиях завершения перемещения данных.
PIDCallbackHandle
RAM Disk PID назначает адрес подходящей структуры для передачи как первый аргумент в вызов функции, определенной полем PIDCallbackFunction.

ADI_FSS_LBA_REQUEST. Эта структура представляет запрос LBA, и она используется для передачи запроса на количество секторов для чтения с устройства. Для передачи запроса в связанной структуре супербуфера ADI_FSS_SUPER_BUFFER должен использоваться адрес этой структуры в поле LBARequest. Структура ADI_FSS_LBA_REQUEST определена в заголовочном файле FSS adi_fss.h следующим образом:

typedef struct ADI_FSS_LBA_REQUEST
{
   u32 SectorCount;
   u32 StartSector;
   u32 DeviceNumber;
   u32 ReadFlag;
   ADI_FSS_SUPER_BUFFER *pBuffer;
} ADI_FSS_LBA_REQUEST;

Поля этой структуры назначаются, как показано в следующей таблице:

SectorCount Количество секторов на перемещение данных.
StartSector Начальный сектор перемещаемого блока в формате LBA.
DeviceNumber Номер устройства в цепочке устройств. Для драйвера RAM Disk PID должно быть установлено в 0.
ReadFlag Флаг, показывающий, является ли перемещение данных операцией чтения. Если это так, то здесь должно быть значение 1. Операция записи требует значения 0.
pBuffer Адрес, связанный с подбуфером ADI_FSS_SUPER_BUFFER.

[Передача данных]

Все передачи данных инициируются и завершаются с каждым вызовом adi_dev_Read() или adi_dev_Write(), осуществленным с хендлом устройства RAM Disk PID. После каждого обработанного супербуфера выдается событие ADI_DEV_EVENT_BUFFER_PROCESSED через походящую callback-функцию Device Manager. По завершению обработки всех буферов в цепочке, выдается событие ADI_PID_EVENT_DEVICE_INTERRUPT.

В описании процедуры передачи данных важно разделять события устройства (инициированные физическим носителем данных устройства mass storage device, MSD) и событиями хоста (инициированными программно). В контексте RAM Disk PID передача данных активна от приема запроса LBA для передачи количества секторов и до завершения передачи. Это называют блоком DRQ после его источника ATA. Другими словами, хост рассматривает событие завершения передачи данных как момент, когда он получает callback по завершению обработки каждого ADI_DEV_1D_BUFFER.

Эти callback-и вызываются через Device Manager со следующими аргументами:

1. Аргумент DeviceHandle, предоставленный как третий аргумент, переданный в функцию adi_pdd_Open().
2. Соответствующий код события.
3. Адрес структуры супербуфера для того супербуфера, обработка которого была завершена.

В ответ на эти события FSS сделает вызов в RAM Disk PID с использованием полей PIDCallbackFunction и PIDCallbackHandle fields структуры ADI_FSS_SUPER_BUFFER:

(pSuperBuffer->PIDCallbackFunction) (pSuperBuffer->PIDCallbackHandle,
                                     Event,
                                     pArg);

В этой функции RAM Disk PID будет делать все необходимое для каждого из этих двух событий. Кроме того, в ответ на событие ADI_PID_EVENT_DEVICE_INTERRUPT драйвер RAM Disk PID освободит RAM Disk PID Lock Semaphore, и опубликует семафор RAM Disk PID только если значение SemaphoreHandle ADI_FSS_SUPER_BUFFER равно хендлу семафора RAM Disk PID.

Обработка выданный запрос (обычно выданный драйвером файловой системы File System Driver, FSD) осуществляется следующим образом:

1. Захватывается семафор блокировки (Lock Semaphore) из RAM Disk PID путем передачи пары команда-значение {ADI_FSS_CMD_ACQUIRE_LOCK_SEMAPHORE, NULL}.

2. Затем FSD предоставляет требуемую цепочку буферов для RAM Disk PID через вызов adi_dev_Read() или adi_dev_Write(), например:

adi_dev_Read (..., ADI_DEV_1D, (ADI_DEV_BUFFER*)pSuperBuffer);

Поле LBArequest структуры ADI_FSS_SUPER_BUFFER цепочки, размещенной по адресу pSuperBuffer, должно быть корректно назначено для каждого буфера в цепочке. Вся передача данных будет завершена при возврате из этого вызова.

3. Семафор блокировки (Lock Semaphore), который был захвачен на шаге 1, освобождается FSD/приложением, либо по завершении приема события ADI_PID_EVENT_DEVICE_INTERRUPT.

Диаграмма ниже иллюстрирует поток команды и callback драйвера RAM Disk PID.

RAM Disk PID command and callback flow

[Инициализация драйвера физического интерфейса RAM Disk PID]

В этой секции описывается стадии инициализации, требуемые для RAM Disk PID. Как RAM Disk PID инициализируется - будет зависеть главным образом от того, как он будет использоваться. Возможны следующие сценарии:

• Драйвер постоянно назначен для работы с FSS.
• Драйвер используется совместно и FSS, и другой функцией. Например, RAM Disk может быть подключен к компьютеру хоста через USB, чтобы загрузить файлы носителя, которые впоследствии будут проигрываться встроенным приложением через FSS, как только кабель USB будет отключен.
• Отдельное использование драйвера (без FSS).

Во всех случаях RAM Disk PID требует проведения определенных шагов конфигурирования перед тем, как он может быть использован приложением; отличия в вышеперечисленных сценариях касаются программной части (находящейся в библиотеке FSS или в приложении), которая отвечает за эти шаги. Постоянное назначение только для FSS требует минимальных усилий со стороны приложения; в случае отдельного использования от программиста требуется больше шагов, реализованных в коде приложения.

Перед тем, как показать подготовку RAM Disk PID для каждого сценария, мы сначала опишем каждую из стадий конфигурирования. Стадии конфигурирования RAM Disk PID следующие:

• Открытие.
• Конфигурация.
• Активация.
• Опрос наличия носителя.

Будучи активированным, RAM Disk PID готов к использованию. Чтобы завершить использование RAM Disk PID, требуется выполнить следующие шаги:

• Деактивация.
• Закрытие.

Стадия открытия RAM Disk PID. На этой стадии RAM Disk PID открывается обычным способом для драйвера устройства, этот способ следует стандартной модели драйвера устройства ADI. Структура определения драйвера ADI_RAMDISK_Def (см. секцию с описанием структуры ADI_FSS_DEVICE_DEF) предоставляет большинство из требуемого для вызова adi_dev_Open(), чтобы открыть драйвер устройства RAM Disk PID:

Result = adi_dev_Open (< DeviceManagerHandle >,
                       ADI_RAMDISK_Def.pEntryPoint,
                       ADI_RAMDISK_Def.DeviceNumber,
                       &ADI_RAMDISK_Def.DeviceHandle,
                       &ADI_RAMDISK_Def.DeviceHandle,
                       ADI_RAMDISK_Def.Direction,
                       < DMAManagerHandle >,
                       < DCBQueueHandle >,
                       < Callback-function >);

Также должны быть предоставлены и другие аргументы: < DeviceManagerHandle > и < DMAManagerHandle > были получены при инициализации библиотеки системных служб (System Services Library, SSL) и Менеджера Устройств (Device Manager). < DCBQueueHandle > это хендл очереди DCB (так называемый Менеджер DCB для организации отложенных вызовов функций), если вызовы функции < Callback-function > из RAM Disk PID должны осуществляться с откладыванием запуска, в контексте основного кода программы (рекомендуемый способ вызова callback-функции). Структура ADI_RAMDISK_Def предоставлена в заголовочном файле RAM Disk PID, и доступна в приложении, если определен макрос _ADI_RAMDISK_DEFAULT_DEF_ перед оператором include:

#define _ADI_RAMDISK_DEFAULT_DEF_
#include < drivers/pid/usb/adi_ramdisk.h >

Альтернативно могут быть использованы следующие значения:

Аргумент adi_dev_Open Значение
pEntryPoint &ADI_RAMDISK_Entrypoint
DevNumber 0
Direction ADI_DEV_DIRECTION_BIDIRECTIONAL

Приложению требуется выполнить стадию открытия драйвера RAM Disk PID только в том случае, если этот драйвер используется либо отдельно (без FSS), либо в смешанном сценарии (когда драйвер RAM Disk PID используется как FSS, так и приложением); когда драйвер используется только FSS, она задействует структуру ADI_RAMDISK_Def для открытия драйвера внутри себя.

Чтобы закрыть RAM Disk PID, просто вызовите adi_dev_Close(), передав в параметре хендл устройства RAM Disk PID, например:

adi_dev_Close (ADI_RAMDISK_Def.DeviceHandle);

Стадия конфигурации RAM Disk PID. На этой стадии пары команда-значение передаются в RAM Disk PID через вызов (или вызовы) функции adi_dev_Control().

Таблица команд по умолчанию определена в заголовочном файле RAM Disk PID как инициализированный массив ADI_RAMDISK_ConfigurationTable[]. Его адрес назначается полю pConfigTable структуры ADI_RAMDISK_Def, также определенной в заголовочном файле.

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

Обязательная команда - указать метод потока данных (ADI_DEV_CMD_SET_DATAFLOW_METHOD). Её нужно давать в случае сценария отдельного использования драйвера (без FSS) и для случая смешанного сценария (когда драйвер используется и для FSS, и для приложения); когда драйвер используется FSS, эта команда всегда выдается внутри FSS, так что её специально выдавать не нужно. Команды, требуемые для поведения по умолчанию RAM Disk PID, описаны в заголовочном файле RAM Disk PID, и их можно найти во врезках "Общие команды для драйверов PID" и "Команды, специфические для RAM Disk PID".

У драйвера RAM Disk PID нет настроек по умолчанию.

Стадия активации RAM Disk PID. В стадию активации драйвер RAM Disk PID входит при отправке ему команды ADI_PID_CMD_MEDIA_ACTIVATE, где Value установлено в значение TRUE. Подобным образом драйвер деактивируется, если выдать ту же команду, но в Value указано FALSE.

На входе в эту стадию делаются установки всех нужных выводов GPIO, активируется слой трансляции FLASH, и PID готов принимать запросы для передачи данных в устройство RAM-диска и из него.

Стадия опроса носителя RAM Disk PID. На этой стадии RAM Disk PID должен быть опрошен для детектирования наличия носителя данных. В зависимости от файловой системы, к которой осуществляется доступ, или от того, требуется ли прямой доступ, эта стадия осуществляется за один или два шага.

На первом шаге делается отправка команды ADI_PID_CMD_POLL_MEDIA_CHANGE, результатом которой будет вызов callback с событием ADI_FSS_EVENT_MEDIA_INSERTED. Это событие отправляется в callback-функцию, указанную на стадии открытия - через Менеджер DCB, если он также был указан на стадии открытия - или вызов может быть отправлен напрямую в ту же функцию или другую callback-функцию, путем передачи требуемого адреса функции через команду ADI_PID_CMD_SET_DIRECT_CALLBACK. Последнее обязательно, если второй шаг этой стадии должен быть выполнен из callback-функции. Для обоих сценариев использования совместно с FSS необходимые действия выполняются внутри FSS.

Callback использует следующие аргументы:

o Адрес места в памяти, где содержится хендл устройства RAM Disk PID.
o Событие ADI_FSS_EVENT_MEDIA_INSERTED.
o Адрес переменной u32. Содержимое этой переменной устанавливается драйвером RAM Disk PID в номер устройства (Device Number) устройства в цепочке, для которой был детектирован носитель, если это необходимо. Callback-функция должна установить эту переменную в соответствующий код результата - либо в ADI_FSS_RESULT_FAILED, либо в ADI_FSS_RESULT_SUCCESS, последнее значение показывает, что детектированный носитель был соответствующим образом обработан.

Второй шаг стадии опроса носителя зависит от того, был ли носитель отформатирован под файловую систему, или нет. Это часто важно только для случая, когда использовалась FSS, и опрос был осуществлен внутри неё. Детектирование форматированного раздела (который называется томом, volume) га RAM-диске выполняется отправкой команды ADI_PID_CMD_DETECT_VOLUMES драйверу RAM Disk PID. Если том был детектирован, то вовлекается запуск callback-функции со следующими аргументами:

o Адрес места в памяти, где содержится хендл устройства RAM Disk PID.
o Событие ADI_FSS_EVENT_VOLUME_DETECTED.
o Адрес структуры ADI_FSS_VOLUME_DEF, детализирующей найденный том.

Мы подробно описали каждый из шагов настройки драйвера RAM Disk PID, и теперь нужно вернутся к тому, как эти шаги должны быть использованы в контексте каждого из сценариев использования драйвера. В частности мы подчеркиваем места, выполнение которых находится в зоне ответственности разработчика.

[Назначение RAM Disk PID для постоянного использования службой FSS]

Самый простой из сценариев - исключительное использование RAM Disk PID службой FSS. Мы уже рассматривали в разделе "Быстрый старт", что требуется от приложения, чтобы назначить RAM Disk PID для FSS с настройками по умолчанию. В этой секции мы покажем, что требуется изменить в этих настройках по умолчанию. Например, это может потребоваться, если используется другое устройство RAM-диска; или требуется другой размер зарезервированной области для носителя RAM-диска.

В этих случаях должна быть определен отдельный экземпляр структуры ADI_FSS_DEVICE_DEF. Если будет использоваться такое же имя для экземпляра структуры, как и у структуры ADI_FSS_DEVICE_DEF по умолчанию, то следует проследить, чтобы не был определен макрос _ADI_RAMDISK_DEFAULT_DEF_ перед оператором include, подключающим файл заголовка драйвера RAM Disk PID.

Эта структура потребует адрес структуры ADI_RAMDISK_EntryPoint для точки входа в драйвер RAM Disk PID, и адрес таблицы конфигурации, составленной из пар команда-значение. Структура точки входа и таблица конфигурации по умолчанию определены в заголовочном файле драйвера RAM Disk PID header file, < drivers/pid/ramdisk/adi_ramdisk.h >. Пример таблицы конфигурации и структуры определения может быть следующим:

ADI_DEV_CMD_VALUE_PAIR ADI_RAMDISK_ConfigTable [] =
{
   { ADI_RAMDISK_CMD_SET_RAM DISK_INFO, (void *)&ADI_EZKIT_RAM DISK_Info },
   { ADI_RAMDISK_CMD_SET_RESERVED_SIZE, (void *)10 },
   { ADI_DEV_CMD_END, NULL },
};
 
ADI_FSS_DEVICE_DEF ADI_RAMDISK_Def =
{
   0,
   &ADI_RAMDISK_EntryPoint,
   ADI_RAMDISK_ConfigTable,
   NULL,
   ADI_DEV_DIRECTION_BIDIRECTIONAL,
   'n'
};

Имейте в виду, что зарезервированный размер должен быть всегда такой же, какой использовался для форматирования; значение по умолчанию 10 блоков. Также имейте в виду, что FSS попытается применить указанную точку монтирования по умолчанию с буквой диска для этого устройства. Если буква диска по умолчанию не требуется, то это значение может быть установлено в NULL. Если запрошенная буква недоступна на любой стадии, то FSS назначит следующую доступную букву диска, начиная выбор с буквы "c".

Как только структура ADI_FSS_DEVICE_DEF определена, она просто назначается для FSS следующей парой команда-значение, добавленной к таблице конфигурации FSS, которая передается в вызов adi_fss_Init():

{ ADI_FSS_CMD_ADD_DRIVER, (void*)&ADI_RAMDISK_Def },

Тогда FSS выполнит все стадии инициализации устройства, как было описано выше в разделе "Инициализация драйвера физического интерфейса RAM Disk PID". 

[Регистрация RAM Disk PID со службой FSS]

Если RAM Disk PID предназначен для временного использования в приложении, или если он требует переключения между FSS и USB MSD, то требуется другая процедура для регистрации RAM Disk PID со службой FSS. Этот вариант требует от приложения разработчика управлять стадиями открытия и конфигурации при инициализации устройства, оставляя активацию и опрос носителя на ответственности FSS. Как только RAM Disk PID был сконфигурирован, он может быть зарегистрирован для FSS в любой момент после этого вызовом adi_fss_Init(), либо использованием функции adi_fss_RegisterDevice(), например:

adi_fss_RegisterDevice (&ADI_RAMDISK_Def, < poll-flag >);

Альтернативно регистрация может быть осуществлена передачей пары команда-значение в драйвер функцией adi_dev_Control():

{ ADI_FSS_CMD_REGISTER_DEVICE, (void*)&ADI_RAMDISK_Def },

Аргумент < poll-flag > в функции adi_fss_RegisterDevice() используется, чтобы определить, должен ли быть RAM Disk PID опрошен на наличие носителя немедленно в момент регистрации. Значение true даст немедленный опрос.

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

Когда RAM Disk PID используется как устройство флешки USB (USB mass storage device), то будут применены те же стадии, как и при регистрации драйвера с FSS. Однако в этом случае вместо этого должен быть осуществлен вызов драйвера класса USB mass storage; хендл драйвера устройства RAM Disk PID отправляется драйверу класса через вызов adi_dev_Control() командой ADI_USB_MSD_CMD_REGISTER_FSSPID:

{ ADI_USB_MSD_CMD_REGISTER_FSSPID, (void*) *)ADI_RAMDISK_Def.DeviceHandle },

Эта команда должна быть использована перед командой ADI_USB_MSD_CMD_SCSI_INIT.

[Инициализация RAM Disk PID для сценария отдельного использования]

Последний рассматриваемый сценарий использования драйвера RAM Disk PID - когда он применен вне контекста FSS или USB mass storage class driver. В этом случае все шаги инициализации, за исключением части детектирования тома стадии опроса носителя, должны быть выполнены непосредственно в приложении разработчика.

Будет определена callback-функция для обработки событий, перечисленных ниже. Все эти события первым аргументом в вызове callback-функции получают адрес, который указывает на место размещения хендла устройства RAM Disk PID, и аргумент the Event будет одним из следующих перечисленных значений, и третий аргумент будет интерпретироваться в соответствии с кодом события Event.

ADI_FSS_EVENT_MEDIA_INSERTED. С этим событием третий аргумент это адрес места нахождения номера устройства (0), для которого осуществлено детектирование носителя. При возврате по этому адресу должен находиться код результата, показывая успешность завершения вызова callback.

ADI_FSS_EVENT_MEDIA_REMOVED. С этим событием третий аргумент не имеет никакого смысла. Предпринимаемое действие будет зависеть от назначения приложения.

ADI_FSS_EVENT_VOLUME_DETECTED. С этим событием третий аргумент содержит адрес структуры ADI_FSS_VOLUME_DEF, содержащей определение тома (volume). Как должна быть заполнена эта структура, см. в секции "ADI_FSS_VOLUME_DEF", описывающей структуру. Предпринимаемое действие будет зависеть от назначения приложения.

ADI_DEV_EVENT_BUFFER_PROCESSED. Это событие, сигнализирующее о завершении трансивера хоста. Подробности см. в разделе "Передача данных".

Дальнейшие действия по обработке события ADI_DEV_EVENT_BUFFER_PROCESSED зависят от назначения приложения. Например, если поле pNext буфера не 0, и значение SectorCount запроса LBA в следующем подбуфере не 0, то может потребоваться действие по постановке следующего запроса LBA с PID, как в случае, когда драйвер используется в фреймворке FSS. Подробности см. в разделе "Передача данных".

ADI_PID_EVENT_DEVICE_INTERRUPT. Это событие завершения передачи устройства. Оно обрабатывается идентично событию ADI_DEV_EVENT_BUFFER_PROCESSED, как это это было описано ранее.

Пример отдельного использования драйвера RAM Disk PID можно рассмотреть в так называемых функциях Raw PID access, которые находятся в модуле исходного кода adi_rawpid.c, находящегося в папке инсталляции VisualDSP++ 5.0 в поддиректории Blackfin\lib\src\drivers\pid\.

[Ссылки]

1. adi_ramdisk.pdf - ADI RAM DISK PHYSICAL INTERFACE DRIVER site:analog.com.
2. VDK: драйверы устройств и системные службы процессоров Blackfin.
3. VisualDSP: работа с динамически выделяемой памятью.
4. Драйвер интерфейса (PID) для службы файловой системы (FSS).
5. Служба файловой системы Blackfin.

 

Добавить комментарий


Защитный код
Обновить

Top of Page