Программирование DSP VDK: служба программируемых флагов Fri, March 29 2024  

Поделиться

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

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

VDK: служба программируемых флагов Печать
Добавил(а) microsin   

В этой статье приведен перевод раздела "Programmable Flag Service" из документации "VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors" [1]. Описывается Служба Программируемых Флагов (programmable flag service, PFS) и её интерфейс программирования (API). PFS в составе библиотеки Системных Служб предоставляют приложению простой в использовании интерфейс к подсистеме программируемых флагов (которые иногда называют порты ввода/вывода общего назначения, или GPIO [4, 5]) процессора Blackfin.

Рассматриваются следующие вопросы:

• Функционирование Programmable Flag Service (PFS)
• Интерфейс программирования PFS (API)
• Публичные типы данных, перечисления и макросы, связанные с PFS

С использованием возможностей других служб, служба PFS позволяет клиенту управлять направлением флагов, значениями, записываемыми в них, читать уровень на флаге вывода и оповещать клиента об изменении состояния флага вывода с помощью немедленных (live) или отложенных (deferred) функций обратного вызова (callback) [2].

Прим. переводчика: почему-то компания Analog Devices выбрала называть ножки процессора флагами, а программу приложения клиентом. Эти термины в тексте документации встречаются довольно часто, так что помните, что флаги это просто ножки портов GPIO процессора, а клиент - программа приложения либо поток, который работает в этом приложении (если приложение многопоточное, наподобие VDK).

Двунаправленный 16-битный порт F (PF15 .. PF0) имеет дополнительный функционал, в отличие от остальных портов C, D и E. Каждая ножка порта F может индивидуально управляться через так называемую систему управления флагами и состоянием, причем к изменению уровня может быть привязана обработка прерывания. Поэтому ножки порта F называются в руководстве Analog Devices "флагами", что вносит некоторую путаницу. Таким образом, регистры порта F и портов C, D и E называются по разному:

Flag direction control register - так называется регистр настройки направления работы (вход или выход) для порта F.
Flag control and status register - так называется регистр состояния и управления состоянием порта F.
GPIO direction control registers - так называются регистры настройки направления работы (вход или выход) для портов C, D и E.
GPIO control and status registers - так называются регистры состояния и управления состоянием для портов C, D и E.

Кроме того, у порта F есть еще 2 дополнительных регистра, связанных с обработкой прерываний:

Flag interrupt mask registers – два регистра маски прерываний позволяют для каждой отдельной ножки PFx функционировать как источник прерывания для процессора. Подобно двум регистрам управления флагами, которые используются для установки и очистки отдельных значений флагов, один регистр маски прерываний флагов установленными битами разрешает функцию прерывания, и другой регистр маски флагов прерываний очисткой бит запрещает функцию прерывания. Ножки портов PFx, определенные для работы в режиме входа, могут быть сконфигурированы для генерации аппаратных прерываний, в то время как выходы портов PFx могут переключаться программно, вызывая срабатывание программных прерываний.

Flag interrupt sensitivity registers – два регистра флагов чувствительности прерывания, определяют для каждой ножки порта PFx, как должно срабатывать прерывание - либо по перепаду, либо по уровню, и если задано срабатывать по перепаду, то задают, по какому перепаду должно срабатывать прерывание - по нарастанию, по спаду или по обоим перепадам сигнала. Один регистр выбирает тип чувствительности, и другой регистр выбирает, какой из перепадов действует для срабатывания прерывания.

Для программируемых флагов Analog Devices написала специальный драйвер, это так называемая служба программируемых программируемых флагов. По сути это просто библиотека, облегчающая портирование кода с одного процессора Blackfin на другой. В статье как раз и описывается эта библиотека.

При полном использовании PFS зависит как от менеджера прерываний [3], так и от менеджера отложенных вызовов функций (deferred callback manager, Менеджер DCB [2]). Если callback-и не откладываются, а остаются немедленными, то тогда Менеджер DCB не требуется. Если и callback-и не требуются, то тогда не нужны ни Менеджер Прерываний, ни Менеджер DCB.

Чтобы уменьшить количество выводов корпусов процессоров, выводы флагов иногда совмещаются (мультиплексируются) с сигналами периферийных устройств процессора на одном и том же выводе корпуса. Служба PFS не предоставляет приложению функцию арбитража для управления мультиплексированием выводов. В зоне ответственности программы остается необходимость правильно настроить периферийные устройства и флаги так, чтобы они не использовали одновременно один и тот же вывод. Для процессоров ADSP-BF531, ADSP-BF532, ADSP-BF533 и ADSP-BF561 это требует гарантии, что правильно установлены регистры управления периферийных устройств. Для процессоров ADSP-BF534, ADSP-BF536, ADSP-BF537 (и более современных) служба PFS автоматически привлекает службу управления портами, чтобы вызвать соответствующие изменения в настройке мультиплексора вывода. Никакое вмешательство пользователя при этом не требуется.

Для ядер процессоров ADSP-BF531, ADSP-BF532, ADSP-BF533 и ADSP-BF561 это влечет за собой необходимость гарантии, что соответствующие регистры управления периферийным устройством установлены корректно. Для ядер процессоров ADSP-BF534, ADSP-BF536, ADSP-BF537 (и будущих) регистры управления портов также должны быть установлены соответствующим образом. Последние могут управляться через службу управления портами (port control service), находящуюся в составе библиотеки Системных Служб. Имейте в виду, что Драйверы Устройств процессоров ADSP-BF534, ADSP-BF536, ADSP-BF537 (и будущих) процессоров делают соответствующие вызовы службы управления портами без какого-либо вмешательства пользователя.

Служба PFS использует не конфликтующую с другими службами систему именования API. Для этого все значения перечислений (enum), операторы определения типа (typedef) используют для PFS-имен префикс ADI_FLAG_, и функции и глобальные переменные используют эквивалентный префикс с буквами в нижнем регистре adi_flag_.

Каждая функция интерфейса программирования (API) службы PFS возвратит код ошибки типа ADI_FLAG_RESULT. Как и у других Системных Служб, нулевой код возврата (ADI_FLAG_RESULT_SUCCESS) показывает отсутствие ошибок. Ненулевые значения показывают ошибку. Как и у всех системных служб, коды ошибки службы PFS уникально отличаются от всех других Системных Служб. Подключаемый файл заголовка adi_flag.h перечисляет все коды ошибок, которые возвращают функции PFS.

Проверка параметров в отладочных версиях библиотеки Системных Служб предоставляют более полный тест параметров API-функции и условий, которые могут привести к ошибкам. Компания Analog Devices настоятельно рекомендует разрабатывать приложения с помощью debug-версий библиотеки Системных Служб, и заключительное тестирование и окончательную разработку следует выполнять на release-версии библиотеки.

[Функционирование Programmable Flag Service (PFS)]

В этом разделе описаны общие принципы работы PFS. Также приведены некоторые подробности для использования API.

Инициализация PFS. Перед использованием службы PFS клиент должен сначала инициализировать эту службу. Для этой цели клиент передает функции инициализации adi_flag_Init параметр, который передается в функцию критического региона кода. Служба PFS нуждается в защите критического региона кода и опционально непрерывной области памяти, которую служба может использовать для флагов callback-ов.

PFS предоставляет возможность вызвать callback при определенных событиях, связанных с флагом, если это указано клиентом и он предоставил callback-функцию прерывания. Подробнее см. раздел "Функции обратного вызова (callback)".

Чтобы обслуживать callback-и и управлять ими, PFS нуждается в небольшом количестве памяти, чтобы сохранять в ней необходимую информацию о каждом callback. Точное количество памяти в байтах определяется макросом ADI_FLAG_CALLBACK_MEMORY. Клиент предоставляет количество памяти, равное ADI_FLAG_CALLBACK_MEMORY столько раз, сколько callback-ов одновременно установлено в любой момент времени.

Например, если одновременно установлены callback-и для двух флагов, то клиент предоставляет ADI_FLAG_CALLBACK_MEMORY * 2 байт памяти. Если не используются callback-и для флагов, то клиентом не нужно предоставлять память.

Завершение PFS. Когда клиенту больше не нужна функциональность службы PFS, вызывается функция завершения adi_flag_Terminate. Эта функция деинсталлирует любые callback-и флагов и любая память, предоставленная для функции инициализации флагов, возвращается обратно клиенту.

Идентификаторы флагов (Flag ID). Все функции API PFS, кроме функция инициализации и завершения, принимают параметр, который идентифицирует управляемый флаг. Этот параметр имеет тип ADI_FLAG_ID и называется идентификатором флага (flag ID). Подключаемый заголовочный файл adi_flag.h службы PFS определяет flag ID для каждого флага, предоставленного процессором. Имена flag ID указываются в форме ADI_FLAG_x, где x уникально идентифицирует отдельный флаг.

Функции управления флагами. В этом разделе описаны функции, управляющие каждым флагом.

adi_flag_Open() вызывается перед любой из функцией управления отдельным флагом. В зависимости от специфического устройства Blackfin, функция adi_flag_Open инициализирует любую аппаратуру, необходимую для работы флага. Например, с ADSP-BF534, ADSP-BF536, ADSP-BF537 (и будущими) процессорами, эта функция конфигурирует логику управления порта с помощью системной службы управления портом для флага, используемого как ножка GPIO. На процессорах ADSP-BF561, ADSP-BF531, ADSP-BF532, ADSP-BF533 эта функция ничего не делает, и просто возвращает управление в вызывающий код (это сделано с целью унификации и упрощения портирования). Описание функции также см. во врезке adi_flag_Open.

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

adi_flag_SetDirection. Флаги можно сконфигурировать как входы или как выходы. Функция adi_flag_SetDirection() используется для установки направления работы флага на вход или выход. Эта функция не меняет значение (состояние уровня) флага. Описание функции также см. во врезке adi_flag_SetDirection.

adi_flag_Set. Когда флаг сконфигурирован как выход, функция adi_flag_Set() устанавливает значение флага в лог. 1, что переводит его в высокий уровень выходного напряжения. Описание функции также см. во врезке adi_flag_Set.

adi_flag_Clear. Когда флаг сконфигурирован как выход, функция adi_flag_Clear() сбрасывает значение флага в лог. 0, что переводит его в низкий уровень выходного напряжения. Описание функции также см. во врезке adi_flag_Clear.

adi_flag_Toggle. Когда флаг сконфигурирован как выход, функция adi_flag_Toggle() инвертирует текущее значение флага. Если флаг был очищен (находился в лог. 0), то эта функция поменяет его значение на установленное (лог. 1). Если флаг был установлен (находился в лог. 1), то эта функция поменяет его значение на очищенное (лог. 0).  Описание функции также см. во врезке adi_flag_Toggle.

adi_flag_Sense. Когда флаг сконфигурирован как вход, функция adi_flag_Sense() может прочитать значение флага, и сохранить это значение в ячейку памяти, предоставленную клиентом. Если флаг очищен (в состоянии лог. 0), то в эту ячейку будет сохранено значение FALSE. Если флаг установлен (в состоянии лог. 1), то в эту ячейку будет сохранено значение TRUE. Описание функции также см. во врезке adi_flag_Sense.

Функции обратного вызова (callback). Наподобие других системных служб, служба PFS использует механизм callback, чтобы оповещать клиентов об асинхронных событиях, происходящих с флагом. Например, пользователь нажал на кнопку, и это вызвало изменение флага, что приведет к генерации события и вызову соответствующей callback-функции.

Программируемые флаги процессора Blackfin могут быть сконфигурированы для генерации прерываний. Служба PFS предоставляет обработчик прерывания, который используется для обработки прерываний от аппаратуры флага. Этот обработчик делает соответствующие вызовы callback-ов в клиентское приложение. Когда клиент установил callback флага, параметр функции установки диктует, как должен быть вызван callback - немедленно (live) в прерывании или вызов будет отложен (deferred) на выполнение после прерывания. Live callback означает немедленный вызов кода callback-функции приложения в контексте обработки прерываний. Deferred callback означает, что callback-функция будет вызвана не в обработчике прерывания, а с более низким приоритетом, с использованием службы DCB (deferred callback, см. [2]).

Когда используется функционал callback службы PFS, клиент не нуждается ни в каких других действиях вне вызовов API PFS. Не нужно вызывать ни Менеджер Прерываний [3], ни Менеджер DCB [2], требуется только инициализация этих служб в случае необходимости.

Может случиться так, что клиентам нужно использовать все возможности службы PFS, но не использовать при этом возможности callback. Если callback-и не используются клиентом, то не нужно предоставлять память для функции инициализации службы PFS.

adi_flag_InstallCallback. Функция adi_flag_InstallCallback() используется для установки callback-а на указанный флаг. В дополнение к flag ID, клиент предоставляет interrupt ID, который флаг должен генерировать, флаг пробуждения (wakeup flag), тип срабатывания вызова callback, адрес callback-функции, хендл клиента и хендл к службе DCB. Описание функции также см. во врезке adi_flag_InstallCallback.

В зависимости от модели процессора Blackfin, программируемые флаги могут генерировать любое из нескольких прерываний (иногда процессор имеет ограничение, какой флаг может генерировать какое прерывание. Подробности можно узнать в соответствующем аппаратном руководстве процессора Blackfin processor Hardware Reference). Идентификатор периферийного устройства (peripheral ID) перечисляет прерывание, генерируемое этим флагом.

Флаг пробуждения показывает, должен ли пробуждаться процессор из режима пониженного энергопотребления, когда происходит событие флага.

Тип срабатывания описывает, при каком условии происходит событие для вызова callback. Поддерживаются следующие типы срабатывания (все они перечислены в подключаемом файле заголовка adi_flag.h):

• Высокий уровень – вызов callback генерируется при наличии на флаге уровня лог. 1.
• Низкий уровень – вызов callback генерируется при наличии на флаге уровня лог. 0.
• Перепад нарастания – вызов callback генерируется при наличии на флаге перехода уровня от лог. 0 к лог. 1.
• Перепад спада – вызов callback генерируется при наличии на флаге перехода уровня от лог. 1 к лог. 0.
• Оба перепада – вызов callback генерируется на любом переходе уровня (обратите внимание, что этот вариант не поддерживается на моделях процессоров ADSP-BF54x).

Адрес callback-функции задает функцию обратного вызова типа ADI_DCB_CALLBACK_FN (см. описание службы DCB [2] для получения дополнительной информации об этом типе функции). Будучи вызванной, callback-функция получает 3 параметра:

• ClientHandle – значение, предоставленное клиентом, когда callback был установлен.
• ADI_FLAG_EVENT_CALLBACK – показывает событие для callback флага.
• FlagID – идентификатор флага (flag ID), задающий флаг, для которого генерируется callback.

Когда в функцию adi_flag_InstallCallback передается параметр хендла службы DCB, равный NULL, то callback будет выполнен немедленно (live), т. е. прямо из контекста обработки прерывания. Если же хендл службы DCB не NULL, то служба PFS использует службу DCB для запуска callback-функции.

Одна callback-функция может быть использована и установлена для любого количества флагов; эта универсальная callback-функция может использовать параметр FlagID, чтобы определить, какой именно флаг привел к генерации вызова callback. Однако имейте в виду, что для определенного флага должен быть установлен только один callback.

Функция установки callback adi_flag_InstallCallback не меняет настройку флага (например его направление) и состояние флага. Описание функции также см. во врезке adi_flag_InstallCallback.

adi_flag_RemoveCallback. Функция adi_flag_RemoveCallback() используется для удаления callback для указанного флага. Эта функция запрещает генерацию прерывания для флага, и удаляет callback из своих внутренних таблиц. Нельзя больше будет ожидать срабатывания callback-ов для указанного флага, для этого потребуется повторная установка callback. После вызова функции adi_flag_RemoveCallback для службы PFS освободится память, используемая под callback, и эту память можно использовать для установки другого callback. Функция adi_flag_RemoveCallback не меняет настройку флага (например его направление) и состояние флага. Описание функции также см. во врезке adi_flag_RemoveCallback.

adi_flag_SuspendCallbacks. Функция adi_flag_SuspendCallbacks() используется для временной приостановки срабатывания callback-ов для указанного флага, но сам callback при этом не деинсталлируется. Эта функция обычно используется совместно с функцией adi_flag_ResumeCallbacks. Описание функции также см. во врезке adi_flag_SuspendCallbacks.

adi_flag_ResumeCallbacks. Функция adi_flag_ResumeCallbacks() используется для возобновления работы callback-ов, когда их работа была приостановлена функцией adi_flag_SuspendCallbacks function. Подробнее см. во врезке adi_flag_ResumeCallbacks.

adi_flag_SetTrigger. Функция adi_flag_SetTrigger() устанавливает условие для флага, которое вызывает срабатывание callback. Эта функция обычно не вызывается клиентами, потому что условие срабатывание автоматически задается функцией adi_flag_InstallCallback. Функция adi_flag_SetTrigger предоставлена для удобства тех пользователей, которые хотят получить дополнительную возможность управления callback-ами. Описание функции также см. во врезке adi_flag_SetTrigger.

В этой врезке описывается пример кода, показывающий пример использования PFS. В этом примере служба PFS инициализируется, один флаг конфигурируется как вход, другой как выход. Также показано, как можно управлять флагом выхода и как использовать callback-функцию для реагирования на изменения состояния входного флага. Все функции службы PFS вернут код ошибки (если ошибок не было, то будет возвращен код ADI_FLAG_RESULT_SUCCESS). На практике этот код ошибки должен быть проверен, чтобы убедиться в успешном завершении функции API PFS. В этом примере код возврата не проверяется.

Инициализация PFS. Перед использованием службы PFS она должна быть инициализирована. Следующий фрагмент инициализирует службу PFS и предоставляет ей память для одной callback-функции.

// Память для службы:
static u8 FlagServiceData[ADI_FLAG_CALLBACK_MEMORY * 1];
// Возвращаемое значение:
ADI_FLAG_RESULT Result;
// Количество поддерживаемых callback-ов:
u32 ResponseCount;
 
Result = adi_flag_Init(FlagServiceData, sizeof(FlagServiceData),
                       &ResponseCount, NULL);

После завершения этого кода служба PFS инициализирована и готова для использования.

Открытие флага. После того, как служба была инициализирована, могут быть открыты любые флаги для использования. В этом примере используются 2 флага.

Result = adi_flag_Open(ADI_FLAG_PF0);
Result = adi_flag_Open(ADI_FLAG_PF1);

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

Установка направления работы флага. После того, как флаг открыт, для него нужно установить направление работы - на выход или на вход. В этом примере один флаг конфигурируется как вход, другой как выход.

Result = adi_flag_SetDirection(ADI_FLAG_PF0, ADI_FLAG_DIRECTION_INPUT);
Result = adi_flag_SetDirection(ADI_FLAG_PF1, ADI_FLAG_DIRECTION_OUTPUT);

После того, как направление флага установлено, им можно управлять (если это выход), и/или можно считывать его значение.

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

Result = adi_flag_Set(ADI_FLAG_PF0);      // установка выхода в лог. 1
Result = adi_flag_Clear(ADI_FLAG_PF0);    // установка выхода в лог. 0
Result = adi_flag_Toggle(ADI_FLAG_PF0);   // переключение уровня выхода

Первый вызов установит высокий уровень на выходе, и второй вызов установит низкий уровень на выходе. Третий вызов переключит текущее значение флага на противоположное.

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

u32 Value;  //Переменная, куда будет сохранено состояние флага.
Result = adi_flag_Sense(ADI_FLAG_PF0, &Value);// Проверка состояния флага:if (Value == TRUE)
{
   // Здесь действия для лог. 1 на флаге:
   ...
}else
{
   // Здесь действия для лог. 0 на флаге:
   ...
}

Этот код показывает, как может быть прочитано значение флага, и как на основе этого значения можно предпринять какие-то условные действия. Если такие проверки делать регулярно с заданными интервалами времени, то такая работа с флагом называется методом опроса (polling). Альтернативно может для той же цели использоваться callback-функция, которая оповестит приложение о событии изменения значения флага, когда такое изменение произойдет.

Установка callback-функции. Чтобы избежать вычислительных потерь на опрос флага, вместо него можно использовать вызов callback-функции, когда меняется состояние вывода. Для этого приложение должно установить callback-функцию. Следующий фрагмент кода показывает, как установить callback-функцию, и как она может работать.

...
Result = adi_flag_InstallCallback(ADI_FLAG_PF1, ADI_INT_PFA,
                                  ADI_FLAG_TRIGGER_LEVEL_HIGH,
                                  TRUE, (void *)0x12345678, NULL, Callback);
...
 
void Callback(void *ClientHandle, u32 Event, void *pArg)
{
   // ClientHandle = 0x12345678
   // Event = ADI_FLAG_EVENT_CALLBACK
   switch ((ADI_FLAG_ID)pArg)
   {
   case ADI_FLAG_PF1:
      // В этом месте нужно выполнить код, связанный
      // с изменением состояния флага PF1:
      break;
   // тут могут быть добавлены обработки и для других флагов:
   //case ...:
   //   break;
   }
}

Когда запускается callback-функция, параметр ClientHandle получит значение, которое было указано при установке callback-а (в нашем примере 0x12345678), а Event это значение ADI_FLAG_EVENT_CALLBACK, и параметр pArg содержит флаг, который вызвал срабатывание callback.

Приостановка и возобновление работы callback. Если приложению нужно временно прекратить обработку callback-ов, то следующий фрагмент кода показывает, как это можно сделать.

Result = adi_flag_SuspendCallbacks(ADI_FLAG_PF1);

После этого callback-функция для флага PF1 больше не будет вызываться, когда произойдет событие флага. Фрагмент ниже показывает, как возобновить обработку callback-ов.

Result = adi_flag_ResumeCallbacks(ADI_FLAG_PF1);

Теперь callback-функция будет снова вызываться, когда происходит событие по заданному условию.

Удаление callback-ов. Если приложению больше не нужен callback, он удаляется следующим вызовом.

Result = adi_flag_RemoveCallback(ADI_FLAG_PF1);

После этого callback-функция больше не будет вызываться, и обработка этой callback-функции удаляется из службы PFS. Память, которая была задействована для этого, становится теперь доступна для службы PFS, так что эту память можно задействовать повторно для установки другой callback-функции.

Завершение PFS. Когда функционал службы PFS больше не нужен, приложение останавливает эту службу. Следующий фрагмент завершает работу службы PFS.

ADI_FLAG_RESULT Result;          // возвращаемое значение
Result = adi_flag_Terminate();

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

[Интерфейс программирования PFS (API)]

В этом разделе предоставлено описание API PFS.

! Приведенное здесь описание было точным на момент создания этого документа. Однако следует проверить содержимое подключаемого файла adi_flag.h службы PFS, чтобы получить самую обновленную информацию.

Функция adi_flag_Clear устанавливает значение флага в лог. 0, переводя выходную ножку порта в низкий уровень.

ADI_FLAG_RESULT adi_flag_Clear(ADI_FLAG_ID FlagID);

Аргумент:

FlagID Значение из перечисления, уникально идентифицирующее флаг.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Close вызывается, когда определенный флаг больше не нужен приложению. В настоящее время эта функция не выполняет никаких действий и просто выполняет немедленный возврат. Будущие модели процессоров Blackfin могут потребовать от этой функции каких-нибудь манипуляций с аппаратурой, когда флаг закрывается.

ADI_FLAG_RESULT adi_flag_Close(ADI_FLAG_ID FlagID);

Аргумент:

FlagID Значение из перечисления, уникально идентифицирующее закрываемый флаг.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Init предоставляет и инициализирует память для службы PFS. Эта функция должна вызываться только один раз на ядро. Если она вызывается больше одного раза, то для каждого вызова должна быть предоставлена отдельная область памяти.

ADI_FLAG_RESULT adi_flag_Init(void *pMemory,
                              const size_t MemorySize,
                              u32 *pMaxEntries,
                              void *pEnterCriticalArg);

Аргументы:

pMemory Указатель на область памяти, используемой для хранения данных, требуемых для службы PFS.
MemorySize Размер в байтах памяти, предоставленной под данные службы PFS.
pMaxEntries При возврате из функции эта ячейка памяти будет заполнена максимальным возможным количеством одновременно активных callback-ов, которое может поддержать служба PFS на предоставленном объеме памяти.
pEnterCriticalArg Хендл на область данных, содержащих критический регион данных. Это значение передается в функцию adi_int_EnterCriticalRegion, где используется для внутренних целей модуля. Подробности см. в описании Менеджера Прерываний [3].

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Служба PFS была успешно инициализирована.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Open конфигурирует любою аппаратуру, необходимую для работу указанного флага как порта ввода/вывода общего назначения (general-purpose I/O, GPIO). В зависимости от конкретного типа процессора Blackfin, эта функция инициализирует любую необходимую аппаратуру для работы флага. Например, процессоры ADSP-BF534, ADSP-BF536, ADSP-BF537 (и будущие модели) с помощью этой функцией конфигурируют управляющую логику порта, задействуя для этого системную службу управления портами, после чего указанный флаг может работать как вывод GPIO. На процессорах ADSP-BF531, ADSP-BF532, ADSP-BF533 и ADSP-BF561 эта функция ничего не делает, и просто возвращает управление в вызывающий код.

ADI_FLAG_RESULT adi_flag_Open(ADI_FLAG_ID FlagID);

Аргумент:

FlagID Значение из перечисления, уникально идентифицирующее флаг для открытия.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Sense считывает значение флага. Эта функция сохраняет значение TRUE в предоставленное место в памяти, если флаг находится в состоянии лог. 1. Если флаг находится в состоянии лог. 0, то в эту ячейку будет записано значение FALSE.

ADI_FLAG_RESULT adi_flag_Sense(ADI_FLAG_ID FlagID, u32 *pValue);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг для опроса.
pValue Указатель на ячейку памяти, куда будет сохранено значение флага.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

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

ADI_FLAG_RESULT adi_flag_Toggle(ADI_FLAG_ID FlagID);

Аргумент:

FlagID Значение из перечисления, уникально идентифицирующее управляемый флаг.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Terminate закрывает службу PFS. Любые установленные callback-и удаляются, и вся предоставленная при инициализации PFS память освобождается и возвращается приложению. Если служба PFS остановлена, функция инициализации PFS должна быть вызвана снова перед тем, как можно будет использовать любую API-функцию PFS.

ADI_FLAG_RESULT adi_flag_Terminate(void);

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_Set установит значение флага в лог. 1, переводя выход порта флага в высокий уровень.

ADI_FLAG_RESULT adi_flag_Set(ADI_FLAG_ID FlagID);

Аргумент:

FlagID Значение из перечисления, уникально идентифицирующее управляемый флаг.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

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

ADI_FLAG_RESULT adi_flag_SetDirection(ADI_FLAG_ID FlagID,
                                      ADI_FLAG_DIRECTION Direction);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее управляемый флаг.
Direction Направление, в котором конфигурируется флаг.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_SetTrigger устанавливает условие, по которому будет срабатывать callback. Эта функция обычно не вызывается клиентами, поскольку условие срабатывания настраивается автоматически при установке callback-функции adi_flag_InstallCallback.

Эта функция предоставлена для удобства тех пользователей, которые хотят получить дополнительное управление callback-ами. Она позволяет менять условие срабатывания без удаления и переустановки callback-а.

ADI_FLAG_RESULT adi_flag_SetTrigger(ADI_FLAG_ID FlagID,
                                    ADI_FLAG_TRIGGER Trigger);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг.
Trigger Условие срабатывания для callback.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_InstallCallback инсталлирует callback-функцию, которая должна быть вызвана всякий раз, когда выполнятся определенное событие, заданное для указанного флага. Обратите внимание, что callback-функция, предоставленная вызывающим кодом, это именно функция обратного вызова, а не обработчик прерывания.

Функция adi_flag_InstallCallback не меняет значения флага и его направления.

ADI_FLAG_RESULT adi_flag_InstallCallback(ADI_FLAG_ID FlagID,
                                         ADI_INT_PERIPHERAL_ID PeripheralID,
                                         ADI_FLAG_TRIGGER Trigger,
                                         u32 WakeupFlag,
                                         void *ClientHandle,
                                         ADI_DCB_HANDLE DCBHandle,
                                         ADI_DCB_CALLBACK_FN ClientCallback);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг, на который устанавливается callback.
PeripheralID Идентификатор периферийного устройства, которое задает системное прерывание для используемого флага (см. описание Менеджера Прерываний и adi_int.h [3]).
Trigger Условие срабатывания для callback.
WakeupFlag Флаг, показывающий, должен ли процессор пробуждаться из режима пониженного энергопотребления, когда срабатывает callback.
ClientHandle Идентификатор, определенный и предоставленный клиентом. Это значение передается в callback-функцию.
DCBHandle Если здесь указано значение NULL, то будут использоваться live callback-и, или хендл к службе DCB [2], если будут использоваться отложенные вызовы для callback-ов.
ClientCallback Адрес клиентской callback-функции.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_RemoveCallback удаляет callback для указанного флага, и запрещает для него генерацию прерывания, вызывающего callback-функцию. Эта функция не меняет значения флага, направления и т. д.

! Вызов adi_flag_RemoveCallback из callback-функции не поддерживается, и может привести к неопределенному поведению.

ADI_FLAG_RESULT adi_flag_RemoveCallback(ADI_FLAG_ID FlagID);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг, для которого callback будет удален.

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_ResumeCallbacks возобновляет запуск callback-функции, когда генерация callback-ов была приостановлена функцией adi_flag_SuspendCallbacks. Эта функция просто возобновляет работу прерывания, которое вызывает callback.

ADI_FLAG_RESULT adi_flag_ResumeCallbacks(ADI_FLAG_ID FlagID,
                                         ADI_INT_PERIPHERAL_ID PeripheralID);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг, для которого будет возобновлена работа callback.
PeripheralID Указывает системное прерывание, используемое для флага (см. описание Менеджера Прерываний и файл adi_int.h [3]).

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

Функция adi_flag_SuspendCallbacks временно приостанавливает callback-и для указанного флага, без деинсталляции callback. Эта функция обычно используется совместно с функцией adi_flag_ResumeCallbacks. Эта функция просто запрещает прерывание для указанного вывода, которое вызывало callback.

ADI_FLAG_RESULT adi_flag_SuspendCallbacks(ADI_FLAG_ID FlagID,
                                          ADI_INT_PERIPHERAL_ID PeripheralID);

Аргументы:

FlagID Значение из перечисления, уникально идентифицирующее флаг, для которого будет приостановлена работа callback.
PeripheralID Указывает системное прерывание, используемое для флага (см. описание Менеджера Прерываний и файл adi_int.h [3]).

Возвращаемые значения:

ADI_FLAG_RESULT_SUCCESS Функция завершилась успешно.
любое другое значение Произошла ошибка. См. коды ошибок во врезке ADI_FLAG_RESULT.

[Публичные типы данных, перечисления и макросы, связанные с PFS]

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

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

Тип перечисления ADI_FLAG_ID уникально определяет каждый флаг в целевом процессоре. Для клиентского приложения идентификаторы флагов (flag ID) это просто значения, которые идентифицируют определенный флаг; однако каждый flag ID в действительности состоит из 2 информационных частей.

Старшие 16 бит перечисления задают позицию бита внутри порта, которая соответствует этому флагу. Младшие 16 бит это смещение для системных регистров флага, что управляют флагом. Предоставленный макрос создает flag ID, который содержит позицию бита и смещение регистра. Также предоставлены макросы, которые распаковывают позицию бита и смещение регистра из предоставленного flag ID.

Приложения редко нуждаются, если вообще когда-нибудь это происходит, в доступе к этим макросам; однако они предоставлены для обращения в файле adi_flag.h. Приложения обычно используют только полностью составленное значение ID. Заранее установленный список значений перечисления слишком велик, чтобы его приводить здесь, достаточно помнить, что он имеет форму ADI_FLAG_Pxy, где x идентифицирует порт (например C, F, E, ...) и y это индекс ножки порта флага. Подробности см. в файле adi_flag.h.

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

ADI_FLAG_CREATE_FLAG_ID Создает flag ID для указанной позиции бита и смещения регистра.
ADI_FLAG_GET_BIT Получает позицию бита для указанного flag ID.
ADI_FLAG_GET_OFFSET Получает смещение регистра для указанного flag ID.
ADI_FLAG_GET_MASK Создает маску для указанного flag ID, которую можно использовать в манипулировании регистрами управления аппаратурой для указанного флага.

Перечисление ADI_FLAG_DIRECTION определяет направление работы (вход это или выход) для вывода флага.

ADI_FLAG_DIRECTION_INPUT Флаг конфигурируется как вход.
ADI_FLAG_DIRECTION_OUTPUT Флаг конфигурируется как выход.

Перечисление ADI_FLAG_EVENT определяет тип события для callback. Имеется только одно значение, ADI_FLAG_EVENT_CALLBACK. Этот тип перечисления отличается от всех других типов события для Системных Служб - для любой службы может быть использована одна callback-функция, независимо от обрабатываемого события. Коды событий для службы PFS начинаются со значения ADI_FLAG_ENUMERATION_START, чтобы упростить идентификацию события.

ADI_FLAG_EVENT_CALLBACK Сработало условие запуска callback для указанного флага.

Каждая функция API службы флагов возвращает значение из перечисления ADI_FLAG_RESULT как код возврата. Как и все системные службы, обычный код успешного возврата определен как 0, и код обычной ошибки определен как 1. Это позволяет вызывающей функции быстро оценить код возврата на нулевое (не было ошибки) или не нулевое (ошибка была) значение. Все подробные коды возврата для службы PFS начинаются со значения ADI_FLAG_ENUMERATION_START, чтобы проще идентифицировать значения.

Мнемоника Код Описание
ADI_FLAG_RESULT_SUCCESS 0 Обычный успешный результат вызова.
ADI_FLAG_RESULT_FAILED 1 Обычная неудача вызова.
ADI_FLAG_RESULT_INVALID_FLAG_ID 0x80001 Недопустимый идентификатор флага.
ADI_FLAG_RESULT_INTERRUPT_MANAGER_ERROR 0x80002 Ошибка, которую возвратил Менеджер Прерываний.
ADI_FLAG_RESULT_ERROR_REMOVING_CALLBACK 0x80003 Для указанного идентификатора не был установлен callback.
ADI_FLAG_RESULT_ALL_IN_USE 0x80004 Все слоты флагов находятся в использовании.
ADI_FLAG_RESULT_PORT_CONTROL_ERROR 0x80005 Ошибка в управлении портом.
ADI_FLAG_RESULT_NOT_CAPABLE 0x80006 Для указанного флага не может быть запрошенная функция.
ADI_FLAG_RESULT_TRIGGER_TYPE_NOT_SUPPORTED 0x80007 Не поддерживаемый тип триггера.
ADI_FLAG_RESULT_CANT_MAP_FLAG_TO_INTERRUPT 0x80008 Нельзя привязать флаг для указанного прерывания peripheral ID.
ADI_FLAG_RESULT_NOT_MAPPED_TO_INTERRUPT 0x80009 Флаг не привязан к прерыванию.
ADI_FLAG_RESULT_CALLBACK_NOT_INSTALLED 0x8000A Для указанного флага не был установлен callback.
ADI_FLAG_RESULT_BAD_CALLBACK_MEMORY_SIZE 0x8000B Недопустимый макрос ADI_FLAG_CALLBACK_MEMORY (внутренняя ошибка).

Тип перечисления ADI_FLAG_TRIGGER используется для указания условия срабатывания для события, которое вызовет callback-функцию приложения.

ADI_FLAG_TRIGGER_LEVEL_HIGH Условие запуска callback, когда флаг находится в лог. 1.
ADI_FLAG_TRIGGER_LEVEL_LOW Условие запуска callback, когда флаг находится в лог. 0.
ADI_FLAG_TRIGGER_RISING_EDGE Условие запуска callback, когда флаг переходит из лог. 0 в лог. 1.
ADI_FLAG_TRIGGER_FALLING_EDGE Условие запуска callback, когда флаг находится из лог. 1 в лог. 0.
ADI_FLAG_TRIGGER_BOTH_EDGE Условие запуска callback, когда флаг меняет любой лог. уровень.

[Ссылки]

1. VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors site:analog.com.
2. VDK: менеджер отложенных функций обратного вызова.
3. VDK: менеджер прерываний.
4. ADSP-BF538: управление портами GPIO C, D, E.
5. ADSP-BF538: управление портами GPIO F.

 

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


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

Top of Page