Ю. Гончаров EXpressDSP. Часть IV. Ядро реального времени DSP/BIOSЗаканчивая обзор возможностей ядра реального времени DSP/BIOS, мы рассмотрим систему статического и динамического распределения памяти и такую немаловажную часть, как построение аппаратно-независимой модели ввода/вывода, а также разбер╦м пример структуры законченного приложения с использованием DSP/BIOS. Рисунок 1. Потоки данных Распределение памятиВ ядре реального времени DSP/BIOS реализована единая сквозная система динамического и статического распределения памяти. Что же да╦т такой подход по сравнению со ставшим уже традиционным распределением памяти командным файлом? Во-первых - вс╦ статическое распределение памяти сведено в единую систему. Это созда╦т возможность удобного графического конфигурирования и л╦гкой оценки занимаемого объ╦ма. Прич╦м, поскольку в ту же утилиту конфигурации сведены и все настройки параметров средств ядра, то автоматически включаются необходимые для работы секции, например, память для буферов канала, и оценивается необходимый для них объ╦м. При использовании централизованного распределения памяти в программе указываются логические секции. Отображение логической карты памяти в реальную физическую карту и оценка результата производятся при помощи утилиты конфигурации, которая содержит и информацию о стандартных картах памяти поддерживаемого типа ЦСП и введ╦нную разработчиком информацию о дополнительной памяти. Такой подход минимизирует ошибки распределения и позволяет легко переносить приложение на другую аппаратную платформу. Ещ╦ одним радикальным нововведением DSP/BIOS II является система динамического распределения памяти, которая практически является элементом полноценной операционной системы реального времени. Наличие такой системы позволяет существенно улучшить "КПД" использования памяти под временные буферы, особенно в системах со сложной обработкой и большим объ╦мом ОЗУ. Единая модель аппаратно независимого ввода/выводаБазовым процессом практически во всех ЦОС-приложениях является работа данных - получение данных, проведение какой-либо обработки и вывод результатов. Характерной особенностью является то, что как правило работа ид╦т с непрерывными потоками данных. Потоки данных разделяются на блоки, а не на отдельные единичные данные. Таким образом, приложение получает непрерывный поток блоков данных, обрабатывает их и выда╦т результат тоже как правило в виде непрерывного потока блоков данных. Ещ╦ одной особенностью является то, что направление потока данных во время работы не меняется, и он ид╦т в одном направлении от источника к при╦мнику. Возможно наличие множества потоков блоков данных, идущих с разными скоростями в разных направлениях, которые надо обрабатывать асинхронно. Количество кадров данных в потоке также может быть различно и обычно больше одного, то есть, пока ЦСП обрабатывает один кадр данных, оконечное устройство заполняет следующий. Как и в других случаях, потоки в DSP/BIOS делятся на два класса: базовые - менее функциональные, но требующие минимальных дополнительных затрат, так называемые каналы (pipe) , и более универсальные - потоки (stream), имеющие большую функциональность, но и требующие большего объ╦ма кода для обработки. Оба механизма используют механизм передачи через обмен указателями буферов, что позволяет передавать потоки без какого-либо копирования данных. С уч╦том того, что заполнение буферов производится устройством через каналы ПДП, можно сказать, что в передаче данных модели DSP/BIOS сведены к минимуму не только операции копирования, но и все операции, которые нагружают вычислительное ядро ЦСП. Каналы (pipes) - универсальный механизм обмена кадрами данных между задачей-источником и задачей-при╦мником. Механизм каналов занимает малый объ╦м кода и имеет высокую эффективность, но при этом его параметры статически задаются на стадии проектирования, что и позволяет оптимизировать производительность и минимизировать дополнительный объ╦м кода. Потоки (streams) также обеспечивают аппаратно-независимый асинхронный механизм передачи данных, но при этом могут формироваться как статически, так и динамически, а также предоставляют большую гибкость интерфейса. Одной из неотъемлемых составных частей единой системы ввода/вывода являются компоненты, которые выполняют функции согласования стандартизованных потоков ввода/вывода с разнообразным конечным оборудованием и программным обеспечением, а также преобразования этих потоков. Для этой цели в систему DSP/BIOS введено понятие драйвера, то есть программы сопряжения потоков или каналов с конечным оборудованием. Драйверы пишутся для конечного оборудования, например, звуковых кодеков, и включают в себя специфичные для оборудования функции начальной инициализации, настройки и программирования, а также функции получения и записи данных и их преобразования. Драйвер бер╦т на себя все аппаратные проблемы, предоставляя приложению стандартный потоковый интерфейс обмена данными. Каналы (PIPE)Каналы выполняют функцию обеспечения однонаправленного асинхронного обмена данными. Каждый канал владеет буфером, разделенным на фиксированное число кадров фиксированной длины, при этом количество и размер кадров задаются статически в утилите конфигурации DSP/BIOS. Все операции ввода/вывода с любого конца канала производятся в каждый момент времени только с одним кадром. При этом, несмотря на то, что длина кадра фиксирована, приложение может разместить в каждый кадр данный произвольной длины, не превышающей размер кадра. Рисунок 2. Взаимодействие с устройствами ввода/вывода через драйверы Как показано на рис. 3, канал имеет два окончания - передающее и при╦мное. Передающее окончание используется приложением для записи кадров, а при╦мное - для чтения кадров данных. Рисунок 3. Канал данных Канал данных является асинхронным. Процедуры записи и чтения кадра никак между собой не связаны. Для синхронизации обмена используются функции извещения передатчика и при╦мника. Они вызываются, когда кадр данных считывается или записывается для извещения программы о том, что кадр освобожд╦н или поступили данные. Эти функции вызываются автоматически при вызове функций чтения или записи данных из канала с уч╦том наличия свободных кадров. Как было сказано выше, при передаче данных в DSP/BIOS они не копируются, а используется механизм передачи указателей. ДрайверыЛюбая, в том числе и описанная выше система построения обмена потоками данных должна рано или поздно дойти до границы устройства. Любой аппаратно-независимый уровень ввода/вывода в итоге рано или поздно требуется состыковать с реальными устройствами ввода/вывода, например кодеками, которые подключаются к ЦСП через всевозможные интерфейсы и используют различные методы обмена. Для состыковки универсальных потоков и различных устройств обмена служит специальный класс задач - драйверы. С одной стороны, драйвер имеет стандартный интерфейс для обмена потоками данных, а с другой - учитывает особенности используемого устройства. Помимо уч╦та особенностей самого устройства, драйвер должен учитывать и особенности его подключения к данному ЦСП, для чего он взаимодействует со специальными функциями DSP/BIOS, которые в свою очередь, взаимодействуют с библиотекой поддержки конкретного ЦСП (Chip Support Library). Даже для написания такого максимально приближенного к аппаратному обеспечению участка кода, как драйвер, существуют стандартные интерфейсы, позволяющие программировать периферию, к которой подключается оконечное устройство. Например, драйвер подключенного к последовательному порту McBSP кодека должен в принципе программировать как сам последовательный порт, так и контроллер ПДП, через который будет идти обмен. При этом сам драйвер непосредственно программированием порта и контроллера ПДП не занимается, эта задача возлагается на средства DSP/BIOS и утилиту конфигурации. То есть сам код драйвера отвечает только за программирование кодека. С уч╦том того, что драйвер может быть написан на языке высокого уровня, достигается практически полная независимость драйвера от конфигурации конкретного устройства и междуплатформенная переносимость. При написании драйвера используется ряд интерфейсов DSP/BIOS (API). Для стандартизации функций, отрабатываемых драйвером, предусмотрен специальный, так называемый интерфейс ввода/вывода низкого уровня (Low-level I/O - LIO). В состав LIO входят функции управления, функции работы с очередью ввода/вывода и функции сиг-нализации. Список функций привед╦н в табл. 1. Драйвер, отрабатывающий функции LIO, называется LIO интерфейсом (LIO interface) и обеспечивает один или более канал ввода/вывода на одном или нескольких устройствах. Таблица 1. Функции интерфейса LIO
Большинство функций не зависит от направления передачи данных. Это связано с тем, что устройства, которые только выдают или только принимают данные, выполняют практически те же функции, что и устройства, и выдающие и принимающие данные. Основное различие в функциях ввода/вывода заключается в аргументах, которые передаются в функции обмена буферами. В выходном канале переда╦тся заполненный буфер данных, а во входном - пустой буфер. Поскольку операции идентичны, то большая часть управляющего кода в драйвере используется всеми каналами. Функции управления используются для начальной инициализации, включения и выключения устройства и операций управления. Функция инициализации резервирует ресурсы для драйвера (как периферийные модули, так и память) и программирует устройство для установки требуемого режима работы. Как дополнительный аргумент функции инициализации, может передаваться указатель на структуру, содержащую специфичные для данного устройства параметры. Так, например, для кодека это может быть частота дискретизации или другие параметры, такие как номер канала в TDM потоке и коэффициент усиления. Функции работы с очередью ввода/вывода, как видно из названия, осуществляют все операции по обмену буферами данных с устройством. Каждое устройство должно иметь по крайней мере один буфер. Многие устройства, такие как последовательные порты с автобуферизацией или работой через ПДП, также могут иметь схему двойной буферизации. На рис. 4 показано три возможных состояния буфера в драйвере устройства. Рисунок 4. Модель логического устройства с буферами ввода/вывода Вс╦, что находится "внутри" драйвера, обведено штриховой линией. Непосредственно передаваемый в данный момент буфер обычно удерживается в периферийном регистре, например, в регистре источника или при╦мника ПДП, что на рисунке показано в области "периферийное устройство". Область "периферийное устройство" обозначает непосредственно физический модуль, а не логическое устройство. Периферийные устройства с аппаратной очередью, такие как ПДП с перезагружаемыми регистрами, могут "удерживать" в себе несколько буферов для обеспечения непрерывной последовательной передачи. Эта очередь называется "входной" (to device) очередью. Третье положение буфера - это "выходная" (from device) очередь. Как правило, выходная очередь содержит только один элемент - буфер, который только что был передан. Буфер бер╦тся из входной очереди, когда устройство готово передавать очередной буфер. Затем он переда╦тся в периферийный регистр, когда периферийное устройство готово к передаче очередного буфера. Далее буфер переда╦тся в выходную очередь по завершении передачи, что обычно сопровождается генерацией прерывания. То есть буфер в выходной очереди находится начиная с того момента, когда его передача закончена, и до того момента, когда инициирована соответствующая функция, извещающая приложение о том, что буфер свободен. Отметим, что в DSP/BIOS используется как правило работа с указателями буферов, то есть передача буфера не означает его копирование, и фраза "буфер передан в периферийный регистр" обозначает, что в регистр периферийного устройства, например, регистр начального адреса источника контроллера ПДП, записывается указатель на начало буфера и в соответствующий регистр того же контроллера ПДП записывается длина буфера, или выполняется другая аналогичная операция. Заполнение буфера информацией или считывание информации из него производится только непосредственно периферийным модулем. Операция освобождения буфера заключается в том, что драйвер информирует DSP/BIOS и внешнюю программу, что буфер с данным указателем более не используется драйвером. Указанная схема справедлива как для входного потока данных, так и для выходного, с одной только разницей, что в случае входного потока периферийное устройство считывает информацию из буфера, а в случае выходного потока - заполняет буфер информацией. Функции сигнализации. Как видно на рис. 4, по завершении трансфера буфера, обычно генерируется аппаратное прерывание. Это прерывание переводит буфер в выходную очередь и вызывает функцию обратной связи (callback), которая указывается драйверу приложением. Вызов функции обратной связи и извещает приложение о том, что передача буфера завершена. До этого мы рассматривали структуру драйвера одноканального устройства, но многие периферийные устройства могут быть многоканальными. Как пример привед╦м стереоаудиокодеки, или несколько кодеков на одном порту, или поток E1 с временным разделением. В типичном многоканальном потоке данные разделяются во времени при передаче блока, то есть ид╦т первое слово первого канала, затем первое слово второго канала и так далее до первого слова последнего канала, затем ид╦т второе слово первого канала, второе слово второго канала и т.п. Контроллеры ПДП большинства ЦСП TI имеют модуль, который позволяет производить демультиплексирование потока с временным разделением, позволяющий записывать данные каждого канала в свой буфер. На рис. 5 показан пример многоканального потока с временным разделением, который ид╦т через последовательный порт McBSP и контроллер ПДП. Рисунок 5. Работа с многоканальным потоком через контроллер ПДП Пример простейшего приложения с использованием DSP/BIOSРассмотрев основные элементы DSP/ BIOS, привед╦м пример простой задачи с его использованием. Возьм╦м, например, Audio Example от CodeCompo-serStudio. На первом шаге определимся с функ-ционированием структуры, показанной на рис. 6. Рисунок 6. Функциональная структура примера Структура будет производить действия, содержащиеся практически в каждом приложении - получать данные от аудиокодека, производить обработку данных и выдавать данные обратно в аудиокодек. Для упрощения будем просто копировать данные из аудиовхода в аудио-выход. На рис. 7 данная часть обозначена как "Процессы обработки". Рисунок 7. Структура аудиоприложения Кроме обработки аудиоданных в примере, мы будем ещ╦ периодически загружать процессор, чтобы посмотреть, как это будет воздействовать на исполнение приложения. В процессе тестирования эта загрузка будет увеличиваться или уменьшаться, чтобы изменять условия работы приложения. На рис. 7 эта часть обозначена как "Периодические процессы". На этом этапе мы имеем структуру приложения, абстрагированную от е╦ выполнения, и переводим е╦ в процессы DSP/BIOS. Поскольку аудиообработка очень проста, то для не╦ требуется только одна исполняемая нить. Для простоты положим входную и выходную частоты дискретизации аудиосигнала одинаковыми, что позволит использовать один и тот же обработчик аппаратного прерывания HWI для входа и выхода. Мы можем использовать для аудиообработки как нить типа SWI, так и нить типа TSK, однако мы выберем нить типа SWI просто для иллюстрации использования почтового ящика SWI для синхронизации событий с несколькими источниками запуска. При использовании для аудиообработки нити типа TSK с использованием модуля SIO для обмена, такая синхронизация не требуется. Процедура SWI будет запускаться только при полном заполнении входного буфера данными, и при этом для сохранения обработанных данных должен быть доступен пустой буфер. Для управления этими буферами и для иллюстрации использования функции обратной связи, которая будет запускать нить SWI аудиообработки, будем использовать потоки. На рис. 8 показано отображение перечисленных объектов DSP/BIOS на наш процесс обработки. Итого в нашем простом примере имеется одна нить обработчика аппаратного прерывания HWI для обработки прерывания от кодека и одна нить обработчика программного прерывания SWI для управления обработкой аудиоданных. Обработка прерываний представляет собой один поток исполнения, а обработка аудио - другой. Соединяют эти два пути исполнения, или нити, каналы (pipes), которые управляют перемещением буферов данных. Рисунок 8. Отображение структуры на элементы DSP/BIOS Рисунок 9. Структура аудиоприложения с использованием DSP/BIOS В примере также есть независимые от обработки аудио периодические функции, используемые для задания вычислительной нагрузки на процессор. Будем использовать системную тактовую частоту для задания тактовой частоты менеджера периодических процессов PRD, равную 1 кГц (период - одна миллисекунда). У нас есть две периодические функции - функция Load с периодом вызова каждые 8 мс и функция Step, которая активизируется каждые 10 с. Функция Load служит непосредственно для вычислительной загрузки ЦСП, а функция Step изменяет параметры функции Load для увеличения или уменьшения этой загрузки. Рисунок 10. Окно графика исполнения для примера аудиообработки В нашем примере будем основываться на аппаратной базе, используемой в стартовых наборах C6711DSK или C5402DSK. Используемый аудиокодек подключается к последовательному порту McBSP1. Приложение использует обработчик прерывания (DSS_isr()) для взаимодействия с McBSP при обмене данных с кодеком. При этом для обработки аппаратных прерываний используется модуль HWI. Обработчик прерывания от кодека заполняет пустой блок входными данными и выводит данные в кодек из полного блока данных, пока он не освободится. Для обмена данными между обработчиком прерываний и приложениями мы будем использовать каналы данных типа pipe, управляемые модулем PIP. Один канал переда╦т данные от обработчика прерываний к приложению (DSS_rxPipe), а другой - данные для вывода к обработчику прерываний. Функция audio(), присоедин╦нная к нити обработчика программного прерывания (audioSWI), выполняет непосредственно аудиообработку. При этом аудио-обработка активируется только в случае, если имеются оба требуемых блока данных - заполненный входной и пустой выходной. Для синхронизации этих событий мы будем использовать почтовый ящик (mailbox) нити AudioSWI. Начальное значение этого почтового ящика устанавливается равным 3, то есть младшие два бита почтового ящика устанавливаются в единицу. При этом нить SWI запустится на выполнение только когда оба эти разряда будут сброшены в 0. Для индивидуальной очистки битов почтового ящика используются возможности задания функции извещения (notify) от каналов обмена данными. Оба канала извещают обработчик программного прерывания, используя функции SWI_andn() для сброса соответствующего разряда почтового ящика. Входной канал данных извещает audioSWI о том, что обработчик аппаратного прерывания заполнил входной буфер данными вызовом SWI_andn(2) для сброса первого разряда в почтовом ящике. Аналогично, выходной канал вызывает SWI_andn(1) для сброса нулевого разряда почтового ящика, что извещает audioSWI о наличии пустого выходного буфера. На рис. 8 показана конфигурация периодических функций. Напомним, что мы используем системный тактовый сигнал для генерации тактового сигнала менеджера периодических функций с периодом в 1 мс и, в свою очередь, менеджер периодических функций PRD вызывает функцию load() раз в 8 мс и функцию step() - раз в 10 с. Дополнительные ресурсыКак только возникает вопрос, использовать ли стандартные средства или нет, появляется вполне разумное опасение, что в случае с системой реального времени использование какой-либо сервисной функции займ╦т много времени и ресурсов, поэтому не стоит е╦ использовать - лучше вс╦ писать самому. При работе с DSP/BIOS старались учесть эти проблемы и дали разработчику информацию о дополнительных потребностях в ресурсах при любых комбинациях средств DSP/BIOS. Это возможно, поскольку все используемые компоненты DSP/BIOS указываются в утилите конфигурации, которая, как уже говорилось ранее, да╦т полную информацию о занимаемых средствами DSP/BIOS ресурсах. Все вызовы указываются в исполняемом и в явном виде и чтобы получить полную картину, надо только подсчитать все используемые вызовы. Также можно напрямую измерять все дополнительные затраты с использованием средств реального времени. Привед╦м пример подсч╦та дополнительного процессорного времени для нашего примера аудиоприложения. Мы используем следующие компоненты:
Общий объ╦м и занимаемую производительность в тактах процессора средств DSP/BIOS можно узнать из данных, приводимых в документации для конкретного семейства ЦСП на сервере производителя. Как показано в табл. 2, общие дополнительные ресурсы процессора, требуемые для обработки одного кадра аудиоданных, в нашем примере составляют 1351 такт для ЦСП семейства С6000. Таблица 2. Дополнительные ресурсы, требуемые DSP/BIOS при реализации примера на С6000
Период обработки составляет 4 мс, следовательно частота вызова равна 250 Гц. Таким образом, общие дополнительные ресурсы процессора при использовании DSP/BIOS составляют на ЦСП семейства С6000 337,500 или 0,33775 MIPS. Для 200-МГц ЦСП это составляет 0,17% вычислительной мощности процессора. Для подсч╦та требований к памяти DSP/BIOS можно либо опять же просуммировать все требования к памяти вручную, либо воспользоваться помощью утилиты конфигурации, которая предоставит необходимую информацию для заданной конфигурации используемых средств. Использование средств анализа реального времениРанее указывалось, что при помощи средств DSP/BIOS и отладочной среды CodeComposerStudio можно легко и быстро диагностировать и анализировать проблемы исполнения кода в реальном времени. Теперь, когда у нас есть пример приложения, попробуем применить к нему имеющиеся возможности анализа. После компиляции программы мы можем использовать окно "График Исполнения" ExecutionGraph для визуального наблюдения активности нитей или использовать окно сбора статистики StatisticView для сбора и просмотра статистической информации о времени исполнения каждой нити. Статистика, собираемая для функции SWI, измеряет промежуток от времени, когда прерывание готово к исполнению, и до времени, когда его исполнение завершилось. Если максимальное значение этого времени близко к периоду исполнения прерывания или превышает его, система будет иметь проблемы с исполнением в реальном времени. Важно отметить, что средства анализа реального времени собирают информацию и передают е╦ разработчику. А уже прерогатива разработчика - решать, будет программа исполняться в реальном времени или нет. Соответственно, решение, удовлетворяет ли программа условиям для работы в реальном времени или нет, зависит от приложения. В приложении AUDIO DEMO, как мы уже знаем, данные передаются через аудиокодек. Разбер╦м случай исполнения этого примера на отладочном модуле TMS320C6201EVM. В данном случае аудиокодек запрограммирован для работы с частотой дискретизации 48 кГц в стереоформате и работе с 16-разрядными данными. Каждый двухканальный стереоотсч╦т пакуется в одно 32-разрядное слово. Функция DSS_cisr() собирает 96 слов перед тем как передать их через канал как один фрейм. Поскольку функция audio() обрабатывает по одному фрейму за запуск, то номинальная частота запуска функции обработки audiuo() составляет 48 кГц/96 = 500 Гц. Таким образом, максимальное время исполнения объекта audioSWI не должно превышать 1/500 Гц = 2 мс, чтобы не было проблем исполнения в реальном времени. Теперь убер╦м из примера функцию Step(), которая изменяет значение loadVal, определяющее загрузку процессора функцией load(), и, задавая значение loadVal вручную, посмотрим, как оно влияет на время исполнения объекта audioSWI. Как видно из табл. 3, если приоритет audioSWI ниже, чем у PRD_swi, и значение load-Val превышает 100, время исполнения audio-SWI превышает 2 мс. Таблица 3. Влияние времени исполнения объекта audioSWI, в зависимости от загрузки процессора периодическими функциями
Несмотря на то, что audioSWI обрабатывает только один фрейм за один запуск, это вовсе не означает, что период его запуска должен всегда быть меньше периода фрейма во избежание проблем в реальном времени. Например, как вариант, можно увеличить длину канала PIP, чтобы audio() могло ожидать больше доступных фреймов перед тем, как начать обработку нескольких фреймов подряд. Это возможно, поскольку частота PRD_swi составляет 125 Гц, что в четыре раза меньше частоты следования фреймов, которая составляет 500 Гц. Таким образом, как и было сказано ранее, определение того, что мы имеем в виду под "реальным временем", определяется конкретным приложением. Рисунок 11. Пример фоновой функции, используемой для контроля
В случае данного примера мы можем определить ч╦тко: все данные должны быть приняты из DRR и переданы назад в DSR без потерь. Если принять это за критерий работы в реальном времени, то мы можем отследить наличие ошибочных ситуаций пут╦м проверки установки в единицу специальной переменной DSS_error. Эта переменная устанавливается в функции DSS_cisr() в случае, если данные, принятые в DRR, не могут быть переданы в при╦мный канал, поскольку он заполнен, или в случае, если при за-просе данных DXR передающий канал пуст. Крайне нежелательно останавливать процессор при детектировании ошибочной ситуации, поскольку данные от кодека продолжают поступать, и при остановке процессора нарушится работа всего приложения. Для того, чтобы информировать нас о возникновении ошибки, но в то же время не прерывать исполнение приложения, можно использовать модуль TRC. Для этого мы определяем функцию My_Idle(), которая исполняется как фоновый процесс - объект IDL и используется для проверки наличия проблем с реальным временем. Функция исполняется в фоновом режиме и не влияет на исполнение основных задач, но при этом сообщает о детектировании ошибок в окне журнала. С использованием данного метода детектирования ошибок в реальном времени были получены результаты максимальной дополнительной загрузки при разном количестве кадров в канале, которые показаны в табл. 4. Таблица 4. Максимальная дополнительная загрузка процессора при разном количестве кадров в каналах обмена данными
Даже из этого простого примера видно, что критерии исполнения в реальном времени зависят от приложения и конфигурации системы. DSP/BIOS представляет удобные средства анализа и конфигурирования, но итоговое решение всегда оста╦тся за разработчиком. Более полную информацию о DSP/BIOS, среде разработки CodeCompo-serStudio, сигнальных процессорах, а также последние новости о других продуктах Texas Instruments можно узнать на сервере http://www.texas.ru. |
Ваш комментарий к статье | ||||