Программирование DSP VDK: менеджер отложенных функций обратного вызова Mon, October 23 2017  

Поделиться

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

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


VDK: менеджер отложенных функций обратного вызова Печать
Добавил(а) microsin   

В этой статье приведен перевод раздела "Deferred Callback Manager" из документации "VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors" [1]. Описывается менеджер отложенных функций обратного вызова, deferred callback (DCB) manager, используемый разработчиками приложения для управления отложенным выполнением вызовов функции. Имеется также подробное описание интерфейса программирования (API), предоставляемое Менеджером DCB.

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

• Использование Менеджера DCB
• Взаимодействие с RTOS
• Документация API Менеджера DCB
• Публичные типы данных и макросы

Функции обратного вызова (callback functions) обычно используются в приложениях, управляемых событиями, где клиент приложения запрашивает от менеджера службы (такой как Менеджер DMA из библиотеки Системных Служб, SSL) оповещение о том, что запрошенная задача выполнена, например завершена передача DMA, через вызов клиентской функции обратного вызова, указанной клиентом приложения в момент инициализации требуемой службы.

Необходимость вызова клиентской callback-функции обычно возникает, когда выполняется обработчик прерывания ISR с относительно высоким приоритетом. Основное правило таких ISR - как можно меньше занимать времени на свою обработку, и сохранить свое время выполнения максимально определенным и минимально возможным. С другой стороны, callback-функции могут быть длительными, и с неопределенным заранее временем выполнения. В большинстве случаев пользователю было бы предпочтительнее отложить выполнение таких callback-ов на планировщик, работающий с приоритетом ниже, который мог бы быть вытесненным более высокоприоритетными прерываниями. Если делать так, то запрошенная обработка ISR может завершиться с минимальной задержкой.

Менеджер отложенных функций обратного вызова (deferred callback, DCB) из состава Системных Служб предоставляет такой сервис путем обслуживания одной или большего количества очередей отложенных функций обратного вызова, так что их обработка их вызова обычно происходит из функции диспетчера, работающей с приоритетом ниже, чем остальные обработчики прерываний приложения. Такие точки входа в функции обратного вызова ставятся в очередь, с предоставлением адреса требуемой callback-функции вместе с тремя значениями (2 указателя и одно 32-битное целое число без знака), которые передаются в callback-функцию при её (отложенном) запуске.

Менеджер DCB разработан как модуль, работающий отдельно, или совместно с операционной системой реального времени (real-time operating system, RTOS). Реализация модуля имеется для систем Express Logic ThreadX, Green Hills Software INTEGRITY, а так же для VDK компании Analog Devices.

Количество доступных очередей и их длина определяется клиентским приложением в момент инициализации модуля и очереди. От того, как реализован Менеджер DCB (как отдельный модуль или совместно с RTOS), также зависит количество и размер очередей. При реализации совместно с VDK Менеджер DCB может поддерживать только одну очередь с фиксированным уровнем приоритета IVG 14.

Хотя разрешена только одна очередь на один уровень IVG, инженеры могут установить приоритеты для отдельных callback-записей в момент их постановки в очередь. Нет ограничений на количество уровней программного приоритета, которые можно использовать (за исключением практического ограничения на значения числа типа unsigned short). Функция диспетчера пытается выполнить высокоприоритетные callback-и перед теми, у кого программный приоритет ниже, и все они будут выполняться на на одном уровне IVG.

Подробное описание работы Менеджера DCB предоставлено в разделе "Использование Менеджера DCB" вместе с кусками кода, иллюстрирующими его использование в отдельном режиме (без RTOS). Как Менеджер DCB использовать совместно с RTOS, показано в разделе "Взаимодействие с RTOS".

Менеджер DCB использует однозначное соглашение об именовании функций, типов и макросов API, чтобы избежать конфликтов в с другими программными библиотеками, предоставленными ADI (это компания Analog Devices) или другими компаниями. В результате все значения перечисления (enum) и операторы определения типа (typedef) используют префикс ADI_DCB_, и соответственно функции и глобальные переменные используют adi_dcb_, эквивалентный префикс в нижнем регистре.

[Использование Менеджера DCB]

Работа Менеджера DCB состоит в выполнении следующих функций.

• Настройка Менеджера DCB:

Инициализация Менеджера DCB
Открытие очереди

• Обслуживание очереди:

Постановка callback-ов в требуемую очередь
Диспетчеризирование callback-ов по их уровню приоритета (что задается при постановке в очередь)

• Выполнение вспомогательных функций:

Закрытие очереди
Завершение Менеджера DCB

Как все это реализовано - зависит от условий работы Менеджера DCB, т. е. в отдельном приложении (без RTOS), или под управлением механизма отложенных вызовов, предоставляемых RTOS. В любом случае API-вызовы к Менеджеру DCB одинаковые: очередь инициализируется вызовом adi_dcb_Open, и callback-и ставятся в очередь вызовом adi_dcb_Post.

Отложенное выполнение callback-ов планируется по программному приоритету с помощью функции adi_dcb_Dispatch_Callbacks. В рабочем окружении обычного приложения (не RTOS) Менеджер DCB регистрирует (в момент инициализации очереди) подпрограмму обработчика прерывания на желаемом уровне IVG, используя модуль Менеджера Прерываний [2] из библиотеки Системных Служб, и прерывание вызывается каждый раз при постановке в очередь callback-а. Поскольку версия без RTOS использует Менеджер Прерываний, то Менеджер Прерываний должен быть инициализирован перед инициализацией Менеджера DCB.

Следующий код демонстрирует использование без RTOS на одной очереди, инициализированной на уровне IVG 14, с самым низким уровнем IVG, доступным на уровне приложения.

Как уже упоминалось, работа без RTOS требует инициализации Менеджера Прерываний перед инициализацией Менеджера DCB. Если предположить, что пример приложения требует только один обработчик прерывания на один уровень IVG, то Менеджер Прерываний инициализируется следующим кодом:

u32 ne;
adi_int_Init(NULL,0,&ne,NULL);

Инициализация Менеджера DCB памятью, достаточной для одной очереди, следующая:

static char mjk_dcb_Data[ADI_DCB_QUEUE_SIZE];
:
u32 ns;
:
adi_dcb_Init(
   (void*)mjk_dcb_Data, // Адрес используемой памяти.
   ADI_DCB_QUEUE_SIZE,  // Количество байт, требуемых для
                        // требуемого количества серверов очереди.
   &ns                  // На выходе это должно быть таким же,
                        // как требуемое количество очередей.
   NULL                 // Не требуется специальной области данных
                        // для критического региона.
            );

Далее для использования открывается сервер очереди путем передачи достаточной памяти для требуемой длины очереди (в этом примере очередь на 5 записей) и желаемого уровня IVG, на котором работает очередь. Этот уровень игнорируется приложениями, основанными на VDK. Будет возвращен хендл к серверу очереди p_DCB_handle:

static char mjk_dcb_QueueData[5*ADI_DCB_ENTRY_SIZE];
ADI_DCB_HANDLE p_DCB_handle;
:
u32 nqe;
:
adi_dcb_Open(
   14,                        // Требуемый уровень IVG.
   (void*) mjk_dcb_QueueData, // Адрес памяти, используемой для
   5*ADI_DCB_ENTRY_SIZE,      // очереди глубиной в 5 callback-ов.
   &nqe;                      // На выходе это должно быть таким же,
                              // как требуемое количество записей
                              // в очереди (5 для нашего примера).
   &p_DCB_handle              // Возвращаемый handle к серверу очереди.
            );

Теперь Менеджер DCB готов принять постановки в очередь callback-ов для сервера очереди. Обратите внимание, что эта функция обычно выполняется в ISR другой службы. Менеджер DCB передает серверу (идентифицированному по полученному handle) очереди адрес клиентской callback-функции и связанные с ней значения аргументов:

adi_dcb_Post(
   p_DCB_handle,     // Хендл к требуемому серверу очереди.
   0,                // Уровень приоритета.
   ClientCallback,   // Адрес callback-функции.
   pService,         // Адрес экземпляра службы, которая
                     // поставила этот callback в очередь.
   event,            // Флаг, идентифицирующий событие, которое
                     // вызвало прерывание.
   (void*)data       // Адрес данных, относящихся к
                     // callback-функции.
            );

В примере, приведенном выше, event обычно определяет событие (например, завершение передачи DMA) и data обычно указывают на соответствующее место в памяти, которое имеет значение в контексте callback-функции. В контексте Менеджера DMA, этот аргумент - адрес подходящего дескриптора или буфера данных.

По любой причине сброс записей очереди может произойти одним из 2 способов: прямым вызовом функции adi_dcb_Remove, или косвенно вызовом функции adi_dcb_Control. См. описание функции adi_dcb_Terminate для получения подробной информации и примера использования совместно с другими запросами. Следующий код описывает метод прямого вызова:

adi_dcb_Remove(
   p_DCB_handle,     // Хендл для требуемого сервера очереди.
   ClientCallback    // Адрес сбрасываемой callback-функции.
              );

И наконец, если требуется, очередь может быть закрыта и Менеджер DCB остановлен:

adi_dcb_Close(
   p_DCB_handle,     // Хендл к требуемому серверу очереди.
             );
adi_dcb_Terminate();

[Взаимодействие с RTOS]

Менеджер DCB реализует 2 функции, adi_dcb_RegisterISR и adi_dcb_Forward, для интерфейса с различными рабочими окружениями RTOS, включая выделенный режим (standalone mode, работа без RTOS). Эти функции предоставляются в отдельном файле исходного кода adi_dcb_xxxx.c для каждой реализации рабочего окружения, где xxxx идентифицирует требуемую RTOS (например, threadx для Express Logic ThreadX, и integrity для Green Hill Software INTEGRITY), либо standalone для использования без RTOS. Поддержка для VDK реализована так, что эти вышеописанные функции встроены напрямую в VDK. В результате для случая использования рабочего окружения VDK нет эквивалентного файла adi_dcb_vdk.c.

Соответствующий файл adi_dcb_xxxx.c встраивается (или не встраивается) в основной файл adi_dcb.c через операторы условной компиляции, управляемые макросом ADI_SSL_XXXX, где вместо XXXX может быть STANDALONE, THREADX, INTEGRITY или VDK.

В нестоящее время реализации Менеджера DCB предоставлены только для ранее описанных рабочих окружений. Чтобы реализовать эти функции для альтернативных операционных систем (например Linux, FreeRTOS и т. п.), разработчики должны предоставить заменяющие определения в эквивалентных файлах.

В этой секции функции API описаны более подробно.

adi_dcb_Forward. Функция adi_dcb_Forward принимает 2 аргумента. Первый это указатель на структуру ADI_DCB_ENTRY_HDR заголовка записи DCB, и второй это уровень IVG соответствующей очереди. Функция adi_dcb_Forward вызывается из тела функции adi_dcb_Post, и имеет следующий прототип:

void adi_dcb_Forward(
   ADI_DCB_ENTRY_HDR *Entry,
   u16 IvgLevel);

Ниже приведено описание аргументов. 

Entry Указатель на структуру ADI_DCB_ENTRY_HDR. Это совпадает с адресом структуры сервера очереди, с которой callback был поставлен в очередь. Игнорируется standalone-режиме (без RTOS).
IvgLevel Уровень IVG соответствующей очереди. Этот аргумент игнорируется VDK.

Структура ADI_DCB_ENTRY_HDR используется для передачи информации в нижележащее рабочее окружение RTOS, и она описана так:

typedef struct ADI_DCB_ENTRY_HDR {
   struct ADI_DCB_ENTRY_HDR *pNext;
   ADI_DCB_DEFERRED_FNpDeferredFunction;
} ADI_DCB_ENTRY_HDR;

Первое поле в этой структуре это pNext, которое будет NULL на входе в функцию adi_dcb_Forward. В то время как это значение обычно используется для указания на следующий элемент в очереди, его требуемая интерпретация в функции adi_dcb_Forward зависит от специфики реализации RTOS. Второе поле pDeferredFunction устанавливается для указания на функцию adi_dcb_DispatchCallbacks, когда инициализируется очередь. Сервер вызовов отложенных процедур в соответствующей RTOS должен передать указатель в функцию adi_dcb_DispatchCallbacks при выполнении отложенной функции.

adi_dcb_RegisterISR. Функция adi_dcb_RegisterISR вызывается из тела функции adi_dcb_Open, и имеет следующий прототип:

void adi_dcb_RegisterISR(
   u16 IvgLevel,
   ADI_INT_HANDLER_FN Dispatcher,
   ADI_DCB_HANDLE *hServer);

Типы данных определены в заголовочном файле < services/services.h >, и аргументы функции следующие. 

IvgLevel Уровень прерывания, на котором диспетчеризируются callback-и.
Dispatcher Обязательный адрес для функции adi_dcb_DispatchCallbacks.
hServer Адрес структуры сервера очереди.

В выделенной реализации (без RTOS) эта функция регистрирует функцию adi_dcb_DispatchCallbacks с Менеджером Прерываний на указанном уровне прерываний. В реализации VDK она делает возврат без всякого эффекта.

Обработка критических регионов в callback-функции. Если требуется наличие критического региона в теле функции обратного вызова, Вы должны избегать любых ограничений, которые накладывает применение нижележащей RTOS. Например, для VDK-приложения запрещено вызывать PushCriticalRegion/PopCriticalRegion из уровня прерываний.

Если используется VDK-версия Менеджера DCB, вызовы такого плана можно использовать, поскольку callback-функция выполняется на уровне кода ядра. Однако если используется выделенная (без RTOS) версия библиотеки для запуска очереди DCB с приоритетом выше, чем очередь отложенных вызовов VDK, то такие вызовы недопустимы, поскольку callback выполняется на уровне прерывания. В этих случаях эффект критического региона может быть получен прямым использованием встроенных функций cli() и sti().

[Документация API Менеджера DCB]

В этой секции предоставлено описание API-функций Менеджера DCB.

Функция adi_dcb_Close() закрывает очередь DCB для сервера, идентифицируемого по единственному аргументу (хендл сервера), с освобождением слота для последующего использования. В выделенном режиме (без RTOS) функция Менеджера DCB adi_dcb_DispatchCallbacks отцепляется от цепочки обработчиков прерывания на указанном уровне IVG.

ADI_DCB_RESULT adi_dcb_Close(ADI_DCB_HANDLE hServer);

Аргумент:

hServer Хендл на сервер, очередь которого должна быть закрыта.

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

ADI_DCB_RESULT_SUCCESS Очередь успешно закрыта.
ADI_DCB_RESULT_NO_SUCH_QUEUE Предоставленный хендл не соответствует допустимому серверу очереди.
ADI_DCB_RESULT_QUEUE_IN_USE На очереди ожидают своего выполнения не завершенные callback-и. Если об их выполнении не нужно беспокоиться, то сначала сбросьте очередь, перед тем как закрыть её.

Функция adi_dcb_Control() используется для конфигурирования/управления сервером очереди callback-функций в соответствии с парами команда-значение (параметры Command и Value). Для дополнительной информации см. описание ADI_DCB_COMMAND_PAIR. Прототип функции:

ADI_DCB_RESULT adi_dcb_Control(
   ADI_DCB_HANDLE hServer,
   ADI_DCB_COMMAND Command,
   void *Value);

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

• Передается одна пара command-value.

adi_dcb_Control(
   hServer,
   ADI_DCB_CMD_FLUSH_QUEUE,
   (void*)ClientCallback);

• Передача одной пары command-value с использованием структуры.

ADI_DCB_COMMAND_PAIR cmd =
{
   ADI_DCB_CMD_FLUSH_QUEUE,
   (void *)ClientCallback
};
 
adi_dcb_Control(
   hServer,
   ADI_DCB_CMD_PAIR,
   (void*)&cmd);

• Передается таблица (массив) структур ADI_DCB_COMMAND_PAIR. Последней записью в таблице должна быть ADI_DCB_CMD_END.

ADI_DCB_COMMAND_PAIR table[2] =
{
   {
      ADI_DCB_CMD_FLUSH_QUEUE,
      (void*)ClientCallback
   },
   {
      ADI_DCB_CMD_END,
      0
   }
};
 
adi_dcb_Control(
   hServer,
   ADI_DCB_CMD_TABLE,
   (void*)table);

Полный список команд и связанные значения см. в описании ADI_DCB_COMMAND.

Аргументы:

hServer Хендл на сервер, очередь которого должна быть закрыта.
Command Одно из значений перечисления ADI_DCB_COMMAND, которое раскрывает смысл связанного с ним значения аргумента Value. См. описание ADI_DCB_COMMAND.
Value Требуемое значение, одиночное значение, пара команда-значение, или таблица пар команда-значение.

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

ADI_DCB_RESULT_SUCCESS Успешное завершение функции.
ADI_DCB_RESULT_NO_SUCH_QUEUE Предоставленный хендл не соответствует допустимому серверу очереди.
ADI_DCB_RESULT_BAD_COMMAND Неправильно указана команда либо значение.

Функция adi_dcb_Init инициализирует Менеджер DCB с предоставлением достаточного объема памяти для очереди из требуемого количества отложенных вызовов функций. Эта функция может быть вызвана один раз на процессорное ядро.

ADI_DCB_RESULT adi_dcb_Init(
   void *ServerMemData,
   size_t szServer,
   u32 *NumServers
   void *hCriticalRegionData);

Аргументы:

ServerMemData Указатель на область памяти, используемую для хранения данных, связанных с каждым зарегистрированным сервером очереди.
szServer Размер в байтах области памяти, предоставленной для данных сервера очереди.
NumServers При возврате из функции ячейка, на которую ссылается указатель в аргументе будет содержать максимальное количество открытых серверов очереди, которое может поддержать предоставленная область памяти.
hCriticalRegionData Хендл, указывающий на область данных, содержащий критический регион данных. Это передается в adi_int_EnterCriticalRegion, что используется внутри модуля. Подробности см. в документации на Менеджер Прерываний [2].

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

ADI_DCB_RESULT_SUCCESS Был успешно инициализирован сервер очереди.
ADI_DCB_RESULT_NO_MEMORY Обнаружена ошибка нехватки памяти для одной записи очереди.
ADI_DCB_RESULT_CALL_IGNORED Менеджер DCB уже был проинициализирован для этого ядра процессора.

Функция adi_dcb_Open открывает сервер очереди для использования назначенной памяти для её callback-очереди. Дополнительно, в выделенном режиме (без RTOS) очередь назначается на запрашиваемый уровень IVG и функция adi_dcb_DispatchCallbacks Менеджера DCB подцепляется к цепочке обработчиков прерываний с помощью Менеджера Прерываний, для обработки на имеющемся уровне IVG.

! Менеджер Прерываний должен быть инициализирован перед открытием сервера очереди.

ADI_DCB_RESULT adi_dcb_Open(
   u32 IvgLevel,
   void *QueueMemData,
   size_t szQueue,
   u32 *NumEntries,
   ADI_DCB_HANDLE *hServer);

Аргументы:

IvgLevel Уровень IVG, на котором работает функция диспетчера Менеджера DCB. Это значение игнорируется в VDK-версии библиотеки.
QueueMemData Указатель на область памяти, используемой для хранения данных, связанных с записью очереди сервера.
szQueue Размер области памяти, предоставленной для очереди.
NumEntries На выходе из функции этот указатель ссылается на ячейку памяти, которая хранит максимальное количество записей в очереди, которое может обеспечить предоставленный объем памяти.
hServer При выходе из функции этот аргумент содержит ссылку на хендл, указывающий на открытый сервер. Это используется для уникальной идентификации сервера очереди в вызовах других функций API библиотеки Системных Служб.

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

ADI_DCB_RESULT_SUCCESS Сервер очереди был успешно инициализирован.
ADI_DCB_RESULT_NO_MEMORY Обнаружена ошибка нехватки памяти для одной записи очереди.
ADI_DCB_RESULT_QUEUE_IN_USE На указанном IVG сервер уже был открыт.

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

Функция обратного вызова (callback) привязывается к уровню приоритета, так что callback-и с более высоким уровнем приоритета отработают раньше, чем callback-и с низким уровнем приоритета. Чтобы запускать callback-и с одинаковым уровнем приоритета, назначайте параметр Priority одинаковым для каждой постановки в очередь.

ADI_DCB_RESULT adi_dcb_Post(
   ADI_DCB_HANDLE *hServer,
   u32 Priority;
   ADI_DCB_CALLBACK_FN Callback,
   void *pHandle,
   u32 u32Arg,
   void *pArg);

Аргументы (таблица 5-1):

hServer Хендл требуемого сервера очереди.
Priority Уровень приоритета, на котором работает callback. Чем меньше число, тем выше приоритет.
Callback Адрес клиентской функции обратного вызова, для которой запрошен отложенный вызов.
pHandle Адрес void*, передаваемый как первый аргумент для callback-функции при её отложенном вызове. Обычно это адрес (хендл), который становится осмысленным в контексте тела callback-функции. Например, когда этот параметр используется в обработчике прерывания Менеджера DMA, этот аргумент будет значением ClientHandle, определенном, когда был открыт канал DMA.
u32Arg Значение типа u32 (unsigned int), передаваемое как второй аргумент в callback-функцию при её отложенном вызове (см. описание ADI_DCB_CALLBACK_FN). Обычно это значение обретает смысл в контексте кода callback-функции. Например, когда оно используется в обработчике прерывания Менеджера DMA, этот аргумент описывает природу произошедшего события.
pArg Значение void*, передаваемое как третий аргумент для callback-функции при её отложенном вызове (см. описание ADI_DCB_CALLBACK_FN). Обычно это адрес блока данных. Например, когда этот параметр используется в обработчике прерывания Менеджера DMA, этот аргумент указывает на начальную ячейку буфера, для которого завершена передача DMA.

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

ADI_DCB_RESULT_SUCCESS Запись вызова callback-функции успешно добавлена в очередь.
ADI_DCB_RESULT_NO_MEMORY Нет свободных мест в очереди.
ADI_DCB_RESULT_NO_SUCH_QUEUE Предоставленный хендл не соответствует допустимому серверу очереди.

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

ADI_DCB_RESULT adi_dcb_Remove(
   ADI_DCB_HANDLE hServer,
   ADI_DCB_CALLBACK_FN Callback);

Аргументы:

hServer Хендл требуемого сервера очереди.
Callback Адрес удаляемой клиентской функции обратного вызова. Если здесь задано NULL, то из очереди будут удалены все записи, иначе будут удалены все записи, адрес функций обратного вызова в которых совпадает с указанным.

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

ADI_DCB_RESULT_FLUSHED_OK Запись (записи) была успешно удалена.
ADI_DCB_RESULT_NONE_FLUSHED Не было найдено записей для удаления.
ADI_DCB_RESULT_NO_SUCH_QUEUE Предоставленный хендл не соответствует допустимому серверу очереди.

Функция adi_dcb_Terminate() завершает работу Менеджера DCB путем освобождения предоставленной для него памяти (см. описание функции adi_dcb_Init) и данных критического региона.

ADI_DCB_RESULT adi_dcb_Terminate (void);

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

ADI_DCB_RESULT_SUCCESS Успешное завершение функции.

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

Тип данных ADI_DCB_CALLBACK_FN определяет прототип для добавляемых в очередь callback-функций:

typedef void (*ADI_DCB_CALLBACK_FN) (void* pHandle, u32 u32Arg, void* pArg);

Здесь значения аргументов будут переданы функции adi_dcb_Post, когда callback ставится в очередь для отложенного выполнения.

Тип данных ADI_DCB_COMMAND_PAIR используется, чтобы разрешить генерацию таблицы управляющих команд для отправки в Менеджер DCB через функцию adi_dcb_Control.

typedef struct ADI_DCB_COMMAND_PAIR
{
   ADI_DCB_COMMAND kind;
   void *value;
} ADI_DCB_COMMAND_PAIR;

Для допустимых значений полей см. описание ADI_DCB_COMMAND. Например, следующая команда должна быть отправлена Менеджеру DCB, чтобы сбросить все callback-и в очереди:

ADI_DCB_COMMAND_PAIR CMD = { ADI_DCB_CMD_FLUSH_QUEUE, NULL };

Команда ADI_DCB_COMMAND используется для управления сервером очереди Менеджера DCB. Этот тип данных используется в ADI_DCB_COMMAND_PAIR, чтобы поменять значение конфигурации с помощью вызова adi_dcb_Control.

ADI_DCB_CMD_END Определяет конец таблицы пар команда-значение.
ADI_DCB_CMD_PAIR Говорит функции adi_dcb_Control, что передана одна пара команда-значение.
ADI_DCB_CMD_TABLE Говорит функции adi_dcb_Control, что передана таблица пар команда-значение.
ADI_DCB_CMD_FLUSH_QUEUE Адрес callback-функции, для которой будут удалены из очереди все совпадающие по адресу записи, назависимо от их приоритета.

Структура ADI_DCB_ENTRY_HDR предоставляет интерфейс с нижележащей RTOS через функцию adi_dcb_Forward (см. описание функции adi_dcb_Forward):

typedef struct ADI_DCB_ENTRY_HDR (
   struct ADI_DCB_ENTRY *pNext;           // Следующий элемент в очереди.
   ADI_DCB_DEFERRED_FN pDeferredFunction; // Указывает на процедуру отложенного
                                          // вызова (Deferred Callback), здесь
                                          // находится указатель на функцию.
} ADI_DCB_ENTRY_HDR;

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

Определение типа ADI_DCB_DEFERRED_FN задает прототип для этой функции:

typedef void (*ADI_DCB_DEFERRED_FN) (ADI_DCB_ENTRY *);

Все публичные функции Менеджера DCB возвращают код типа ADI_DCB_RESULT. Ниже перечислены его возможные значения.

ADI_DCB_RESULT_SUCCESS Сервер очереди был успешно инициализирован.
ADI_DCB_RESULT_NO_MEMORY Предоставлено недостаточное место в памяти для одной записи очереди.
ADI_DCB_RESULT_QUEUE_IN_USE Для указанного IVG уже был открыт сервер очереди. См. описание ADI_DCB_COMMAND.
ADI_DCB_RESULT_CALL_IGNORED Менеджер DCB уже был инициализирован для этого процессорного ядра. См. описание ADI_DCB_COMMAND.
ADI_DCB_RESULT_NO_SUCH_QUEUE Указанный хендл не соответствует ни одному серверу, зарегистрированному с Менеджером DCB.
ADI_DCB_RESULT_BAD_COMMAND Была неправильно указана либо команда, либо значение.

[Ссылки]

1. VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors site:analog.com.
2. VDK: менеджер прерываний.

 

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


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

Top of Page